diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9da321487..2c5b60b9b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,7 +6,7 @@ on: jobs: setup-ubuntu: - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 steps: - name: Check for GitHub API key @@ -21,14 +21,21 @@ jobs: echo "GitHub API key found." fi + - name: Setup PHP 8.0 and Composer + uses: shivammathur/setup-php@v2 + with: + php-version: '8.0' + tools: composer:v2 + extensions: mbstring, intl, zip, curl, sqlite, pdo_sqlite + coverage: none + + - name: Verify PHP version + run: php -v + - name: Updating Dependencies + zip run: | cd ~ - curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php - HASH=`curl -sS https://composer.github.io/installer.sig` - sudo php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer - - sudo update-alternatives --set php /usr/bin/php8.0 + # Composer already provided by setup-php cd /tmp mkdir linkstack @@ -52,9 +59,7 @@ jobs: cp "../../version.json" "version.json" - composer update --no-scripts - - php artisan lang:update + composer update --no-dev --no-scripts php artisan migrate php artisan db:seed @@ -173,12 +178,12 @@ jobs: TAG_VERSION="${GITHUB_REF##*/}" version=${TAG_VERSION#"v"} - # Install the OpenSSH client - sudo apt-get install -y openssh-client + # Install required clients + sudo apt-get update + sudo apt-get install -y openssh-client sshpass # Clear the remote directory sshpass -p "${{ secrets.SERVER_PASSWORD }}" ssh -o StrictHostKeyChecking=no -p ${{ secrets.SERVER_PORT }} ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }} "rm -rf ${{ secrets.REMOTE_PATH }}/*" # Use SSH to upload the file to the remote server - sshpass -p "${{ secrets.SERVER_PASSWORD }}" scp -o StrictHostKeyChecking=no -P ${{ secrets.SERVER_PORT }} $version.zip ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:${{ secrets.REMOTE_PATH }} - + sshpass -p "${{ secrets.SERVER_PASSWORD }}" scp -o StrictHostKeyChecking=no -P ${{ secrets.SERVER_PORT }} $version.zip ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_IP }}:${{ secrets.REMOTE_PATH }} \ No newline at end of file diff --git a/README.md b/README.md index 46a3012bd..e6e5c08c6 100644 --- a/README.md +++ b/README.md @@ -30,14 +30,14 @@

-GitHub Repo stars -Mastodon Follow -Discord online user count +GitHub Repo stars +Mastodon Follow +Discord online user count

-GitHub spomsors -Patreon - +GitHub spomsors +Patreon +

--- @@ -45,7 +45,7 @@

Download latest
- GitHub release (latest by date) + GitHub release (latest by date)

--- @@ -169,7 +169,7 @@ The official docker version of [LinkStack](https://github.com/linkstackorg/links The docker version of LinkStack retains all the features and customization options of the [original version](https://github.com/linkstackorg/linkstack). -This docker is based on [Alpine Linux](https://www.alpinelinux.org), a Linux distribution designed to be small, simple and secure. The web server is running [Apache2](https://www.apache.org), a free and open-source cross-platform web server software. The docker comes with [PHP 8.0](https://www.php.net/releases/8.0/en.php) for high compatibility and performance. +This docker is based on [Alpine Linux](https://www.alpinelinux.org), a Linux distribution designed to be small, simple and secure. The web server is running [Apache2](https://www.apache.org), a free and open-source cross-platform web server software. The docker comes with [PHP 8.2](https://www.php.net/releases/8.2/en.php) for high compatibility and performance. #### Using the docker is as simple as pulling and deploying. @@ -221,7 +221,7 @@ The updater may fail without throwing an error and just remain on the current ve ## License -[![License: AGPL v3](https://img.lss.ovh/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) +[![License: AGPL v3](https://img.tny.st/badge/License-AGPL%20v3-blue.svg)](https://www.gnu.org/licenses/agpl-3.0) As of version 4.0.0, the license for this project has been updated to the GNU Affero General Public License v3.0, which explicitly requires that any modifications made to the project must be made public. This license also requires that a copyright notice and license notice be included in any copies or derivative works of the project. diff --git a/app/Functions/functions.php b/app/Functions/functions.php index 6e6350fd8..eacfe19e1 100644 --- a/app/Functions/functions.php +++ b/app/Functions/functions.php @@ -1,48 +1,110 @@ $fingerprint, + 'files' => $files + ]; + if (class_exists('Redis')) { + try { + Redis::setex($cacheKey, $ttl, json_encode($data)); + } catch (\Exception $e) { + // fallback silently + } + } else { + // Laravel cache fallback + Cache::put($cacheKey, $data, $ttl); + } + + $memoryCache[$directory] = $files; + + return $files; + } +} + function findFile($name) { $directory = base_path("/assets/linkstack/images/"); - $files = scandir($directory); - $pathinfo = "error.error"; + $files = preloadDirectoryFiles($directory, 'linkstack_images_files'); + $pattern = '/^' . preg_quote($name, '/') . '(_\w+)?\.\w+$/i'; foreach ($files as $file) { if (preg_match($pattern, $file)) { - $pathinfo = $file; - break; + return $file; } } - return $pathinfo; + return "error.error"; } function findAvatar($name) { $directory = base_path("assets/img"); - $files = scandir($directory); - $pathinfo = "error.error"; + $files = preloadDirectoryFiles($directory, 'assets_img_files'); + $pattern = '/^' . preg_quote($name, '/') . '(_\w+)?\.\w+$/i'; foreach ($files as $file) { if (preg_match($pattern, $file)) { - $pathinfo = "assets/img/" . $file; - break; + return "assets/img/" . $file; } } - return $pathinfo; + return "error.error"; } function findBackground($name) { $directory = base_path("assets/img/background-img/"); - $files = scandir($directory); - $pathinfo = "error.error"; + $files = preloadDirectoryFiles($directory, 'assets_img_background_files'); + $pattern = '/^' . preg_quote($name, '/') . '(_\w+)?\.\w+$/i'; foreach ($files as $file) { if (preg_match($pattern, $file)) { - $pathinfo = $file; - break; + return $file; } } - return $pathinfo; + return "error.error"; } function analyzeImageBrightness($file) { diff --git a/app/Http/Controllers/AdminController.php b/app/Http/Controllers/AdminController.php index 1e356b25e..8dc6874d9 100755 --- a/app/Http/Controllers/AdminController.php +++ b/app/Http/Controllers/AdminController.php @@ -31,737 +31,939 @@ class AdminController extends Controller { - //Statistics of the number of clicks and links - public function index() - { - $userId = Auth::user()->id; - $littlelink_name = Auth::user()->littlelink_name; - $links = Link::where('user_id', $userId)->select('link')->count(); - $clicks = Link::where('user_id', $userId)->sum('click_number'); - - $userNumber = User::count(); - $siteLinks = Link::count(); - $siteClicks = Link::sum('click_number'); - - $users = User::select('id', 'name', 'email', 'created_at', 'updated_at')->get(); - $lastMonthCount = $users->where('created_at', '>=', Carbon::now()->subDays(30))->count(); - $lastWeekCount = $users->where('created_at', '>=', Carbon::now()->subDays(7))->count(); - $last24HrsCount = $users->where('created_at', '>=', Carbon::now()->subHours(24))->count(); - $updatedLast30DaysCount = $users->where('updated_at', '>=', Carbon::now()->subDays(30))->count(); - $updatedLast7DaysCount = $users->where('updated_at', '>=', Carbon::now()->subDays(7))->count(); - $updatedLast24HrsCount = $users->where('updated_at', '>=', Carbon::now()->subHours(24))->count(); - - $links = Link::where('user_id', $userId)->select('link')->count(); - $clicks = Link::where('user_id', $userId)->sum('click_number'); - $topLinks = Link::where('user_id', $userId)->orderby('click_number', 'desc') - ->whereNotNull('link')->where('link', '<>', '') - ->take(5)->get(); - - $pageStats = [ - 'visitors' => [ - 'all' => visits('App\Models\User', $littlelink_name)->count(), - 'day' => visits('App\Models\User', $littlelink_name)->period('day')->count(), - 'week' => visits('App\Models\User', $littlelink_name)->period('week')->count(), - 'month' => visits('App\Models\User', $littlelink_name)->period('month')->count(), - 'year' => visits('App\Models\User', $littlelink_name)->period('year')->count(), - ], - 'os' => visits('App\Models\User', $littlelink_name)->operatingSystems(), - 'referers' => visits('App\Models\User', $littlelink_name)->refs(), - 'countries' => visits('App\Models\User', $littlelink_name)->countries(), - ]; - - return view('panel/index', ['lastMonthCount' => $lastMonthCount,'lastWeekCount' => $lastWeekCount,'last24HrsCount' => $last24HrsCount,'updatedLast30DaysCount' => $updatedLast30DaysCount,'updatedLast7DaysCount' => $updatedLast7DaysCount,'updatedLast24HrsCount' => $updatedLast24HrsCount,'toplinks' => $topLinks, 'links' => $links, 'clicks' => $clicks, 'pageStats' => $pageStats, 'littlelink_name' => $littlelink_name, 'links' => $links, 'clicks' => $clicks, 'siteLinks' => $siteLinks, 'siteClicks' => $siteClicks, 'userNumber' => $userNumber]); - } - -// Users page -public function users() -{ - return view('panel/users'); -} - -// Send test mail -public function SendTestMail(Request $request) -{ + //Statistics of the number of clicks and links + public function index() + { + $userId = Auth::user()->id; + $littlelink_name = Auth::user()->littlelink_name; + $links = Link::where("user_id", $userId)->select("link")->count(); + $clicks = Link::where("user_id", $userId)->sum("click_number"); + + $userNumber = User::count(); + $siteLinks = Link::count(); + $siteClicks = Link::sum("click_number"); + + $users = User::select( + "id", + "name", + "email", + "created_at", + "updated_at", + )->get(); + $lastMonthCount = $users + ->where("created_at", ">=", Carbon::now()->subDays(30)) + ->count(); + $lastWeekCount = $users + ->where("created_at", ">=", Carbon::now()->subDays(7)) + ->count(); + $last24HrsCount = $users + ->where("created_at", ">=", Carbon::now()->subHours(24)) + ->count(); + $updatedLast30DaysCount = $users + ->where("updated_at", ">=", Carbon::now()->subDays(30)) + ->count(); + $updatedLast7DaysCount = $users + ->where("updated_at", ">=", Carbon::now()->subDays(7)) + ->count(); + $updatedLast24HrsCount = $users + ->where("updated_at", ">=", Carbon::now()->subHours(24)) + ->count(); + + $links = Link::where("user_id", $userId)->select("link")->count(); + $clicks = Link::where("user_id", $userId)->sum("click_number"); + $topLinks = Link::where("user_id", $userId) + ->orderby("click_number", "desc") + ->whereNotNull("link") + ->where("link", "<>", "") + ->take(5) + ->get(); + + $pageStats = [ + "visitors" => [ + "all" => visits("App\Models\User", $littlelink_name)->count(), + "day" => visits("App\Models\User", $littlelink_name) + ->period("day") + ->count(), + "week" => visits("App\Models\User", $littlelink_name) + ->period("week") + ->count(), + "month" => visits("App\Models\User", $littlelink_name) + ->period("month") + ->count(), + "year" => visits("App\Models\User", $littlelink_name) + ->period("year") + ->count(), + ], + "os" => visits("App\Models\User", $littlelink_name)->operatingSystems(), + "referers" => visits("App\Models\User", $littlelink_name)->refs(), + "countries" => visits("App\Models\User", $littlelink_name)->countries(), + ]; + + return view("panel/index", [ + "lastMonthCount" => $lastMonthCount, + "lastWeekCount" => $lastWeekCount, + "last24HrsCount" => $last24HrsCount, + "updatedLast30DaysCount" => $updatedLast30DaysCount, + "updatedLast7DaysCount" => $updatedLast7DaysCount, + "updatedLast24HrsCount" => $updatedLast24HrsCount, + "toplinks" => $topLinks, + "links" => $links, + "clicks" => $clicks, + "pageStats" => $pageStats, + "littlelink_name" => $littlelink_name, + "links" => $links, + "clicks" => $clicks, + "siteLinks" => $siteLinks, + "siteClicks" => $siteClicks, + "userNumber" => $userNumber, + ]); + } + + // Users page + public function users() + { + return view("panel/users"); + } + + // Send test mail + public function SendTestMail(Request $request) + { try { - $userId = auth()->id(); - $user = User::findOrFail($userId); - - Mail::send('auth.test', ['user' => $user], function ($message) use ($user) { - $message->to($user->email) - ->subject('Test Email'); - }); - - return redirect()->route('showConfig')->with('success', 'Test email sent successfully!'); + $userId = auth()->id(); + $user = User::findOrFail($userId); + + Mail::send("auth.test", ["user" => $user], function ($message) use ( + $user, + ) { + $message->to($user->email)->subject("Test Email"); + }); + + return redirect() + ->route("showConfig") + ->with("success", "Test email sent successfully!"); } catch (\Exception $e) { - return redirect()->route('showConfig')->with('fail', 'Failed to send test email.'); - } -} - - //Block user - public function blockUser(request $request) - { - $id = $request->id; - $status = $request->block; - - if ($status == 'yes') { - $block = 'no'; - } elseif ($status == 'no') { - $block = 'yes'; - } - - User::where('id', $id)->update(['block' => $block]); - - return redirect('admin/users/all'); - } - - //Verify user - public function verifyCheckUser(request $request) - { - $id = $request->id; - $status = $request->verify; - - if ($status == 'vip') { - $verify = 'vip'; - UserData::saveData($id, 'checkmark', true); - } elseif ($status == 'user') { - $verify = 'user'; - } - - User::where('id', $id)->update(['role' => $verify]); - - return redirect(url('u')."/".$id); - } + return redirect() + ->route("showConfig") + ->with("fail", "Failed to send test email."); + } + } - //Verify or un-verify users emails - public function verifyUser(request $request) - { - $id = $request->id; - $status = $request->verify; - - if ($status == "true") { - $verify = '0000-00-00 00:00:00'; - } else { - $verify = NULL; - } + //Block user + public function blockUser(request $request) + { + $id = $request->id; + $status = $request->block; - User::where('id', $id)->update(['email_verified_at' => $verify]); + if ($status == "yes") { + $block = "no"; + } elseif ($status == "no") { + $block = "yes"; } - //Create new user from the Admin Panel - public function createNewUser() - { - - function random_str( - int $length = 64, - string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' - ): string { - if ($length < 1) { - throw new \RangeException("Length must be a positive integer"); - } - $pieces = []; - $max = mb_strlen($keyspace, '8bit') - 1; - for ($i = 0; $i < $length; ++$i) { - $pieces[] = $keyspace[random_int(0, $max)]; - } - return implode('', $pieces); - } - - $names = User::pluck('name')->toArray(); - - $adminCreatedNames = array_filter($names, function($name) { - return strpos($name, 'Admin-Created-') === 0; - }); - - $numbers = array_map(function($name) { - return (int) str_replace('Admin-Created-', '', $name); - }, $adminCreatedNames); + User::where("id", $id)->update(["block" => $block]); - $maxNumber = !empty($numbers) ? max($numbers) : 0; - $newNumber = $maxNumber + 1; + return redirect("admin/users/all"); + } - $domain = parse_url(url(''), PHP_URL_HOST); - $domain = ($domain == 'localhost') ? 'example.com' : $domain; + //Verify user + public function verifyCheckUser(request $request) + { + $id = $request->id; + $status = $request->verify; - $user = User::create([ - 'name' => 'Admin-Created-' . $newNumber, - 'email' => strtolower(random_str(8)) . '@' . $domain, - 'password' => Hash::make(random_str(32)), - 'role' => 'user', - 'block' => 'no', - ]); - - return redirect('admin/edit-user/' . $user->id); + if ($status == "vip") { + $verify = "vip"; + UserData::saveData($id, "checkmark", true); + } elseif ($status == "user") { + $verify = "user"; } - //Delete existing user - public function deleteUser(request $request) - { - $id = $request->id; - - Link::where('user_id', $id)->delete(); - - Schema::disableForeignKeyConstraints(); - - $user = User::find($id); - $user->forceDelete(); - - Schema::enableForeignKeyConstraints(); - - return redirect('admin/users/all'); - } + User::where("id", $id)->update(["role" => $verify]); - //Delete existing user with POST request - public function deleteTableUser(request $request) - { - $id = $request->id; - - Link::where('user_id', $id)->delete(); - - Schema::disableForeignKeyConstraints(); - - $user = User::find($id); - $user->forceDelete(); - - Schema::enableForeignKeyConstraints(); - } + return redirect(url("u") . "/" . $id); + } - //Show user to edit - public function showUser(request $request) - { - $id = $request->id; + //Verify or un-verify users emails + public function verifyUser(request $request) + { + $id = $request->id; + $status = $request->verify; - $data['user'] = User::where('id', $id)->get(); - - return view('panel/edit-user', $data); + if ($status == "true") { + $verify = "0000-00-00 00:00:00"; + } else { + $verify = null; } - //Show link, click number, up link in links page - public function showLinksUser(request $request) - { - $id = $request->id; - - $data['user'] = User::where('id', $id)->get(); + User::where("id", $id)->update(["email_verified_at" => $verify]); + } - $data['links'] = Link::select('id', 'link', 'title', 'order', 'click_number', 'up_link', 'links.button_id')->where('user_id', $id)->orderBy('up_link', 'asc')->orderBy('order', 'asc')->paginate(10); - return view('panel/links', $data); + //Create new user from the Admin Panel + public function createNewUser() + { + function random_str( + int $length = 64, + string $keyspace = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", + ): string { + if ($length < 1) { + throw new \RangeException("Length must be a positive integer"); + } + $pieces = []; + $max = mb_strlen($keyspace, "8bit") - 1; + for ($i = 0; $i < $length; ++$i) { + $pieces[] = $keyspace[random_int(0, $max)]; + } + return implode("", $pieces); } - //Delete link - public function deleteLinkUser(request $request) - { - $linkId = $request->id; + $names = User::pluck("name")->toArray(); - Link::where('id', $linkId)->delete(); + $adminCreatedNames = array_filter($names, function ($name) { + return strpos($name, "Admin-Created-") === 0; + }); - return back(); - } + $numbers = array_map(function ($name) { + return (int) str_replace("Admin-Created-", "", $name); + }, $adminCreatedNames); + + $maxNumber = !empty($numbers) ? max($numbers) : 0; + $newNumber = $maxNumber + 1; - //Save user edit - public function editUser(request $request) - { - $request->validate([ - 'name' => '', - 'email' => '', - 'password' => '', - 'littlelink_name' => '', - ]); - - $id = $request->id; - $name = $request->name; - $email = $request->email; - $password = Hash::make($request->password); - $profilePhoto = $request->file('image'); - $littlelink_name = $request->littlelink_name; - $littlelink_description = $request->littlelink_description; - $role = $request->role; - $customBackground = $request->file('background'); - $theme = $request->theme; - - if(User::where('id', $id)->get('role')->first()->role =! $role) { - if ($role == 'vip') { - UserData::saveData($id, 'checkmark', true); - } - } - - if ($request->password == '') { - User::where('id', $id)->update(['name' => $name, 'email' => $email, 'littlelink_name' => $littlelink_name, 'littlelink_description' => $littlelink_description, 'role' => $role, 'theme' => $theme]); - } else { - User::where('id', $id)->update(['name' => $name, 'email' => $email, 'password' => $password, 'littlelink_name' => $littlelink_name, 'littlelink_description' => $littlelink_description, 'role' => $role, 'theme' => $theme]); - } - if (!empty($profilePhoto)) { - $profilePhoto->move(base_path('assets/img'), $id . '_' . time() . ".png"); - } - if (!empty($customBackground)) { - $directory = base_path('assets/img/background-img/'); - $files = scandir($directory); - $pathinfo = "error.error"; - foreach($files as $file) { - if (strpos($file, $id.'.') !== false) { - $pathinfo = $id. "." . 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/'), $id . '_' . time() . "." . $request->file('background')->extension()); - } - - return redirect('admin/users/all'); - } - - //Show site pages to edit - public function showSitePage() - { - $data['pages'] = Page::select('terms', 'privacy', 'contact', 'register')->get(); - return view('panel/pages', $data); - } - - //Save site pages - public function editSitePage(request $request) - { - $terms = $request->terms; - $privacy = $request->privacy; - $contact = $request->contact; - $register = $request->register; - - Page::first()->update(['terms' => $terms, 'privacy' => $privacy, 'contact' => $contact, 'register' => $register]); - - return back(); - } - - //Show home message for edit - public function showSite() - { - $message = Page::select('home_message')->first(); - return view('panel/site', $message); - } - - //Save home message, logo and favicon - public function editSite(request $request) - { - $message = $request->message; - $logo = $request->file('image'); - $icon = $request->file('icon'); - - Page::first()->update(['home_message' => $message]); - - if (!empty($logo)) { - // Delete existing image - $path = findFile('avatar'); - $path = base_path('/assets/linkstack/images/'.$path); - - // Delete existing image - if (File::exists($path)) { - File::delete($path); - } - - $logo->move(base_path('/assets/linkstack/images/'), "avatar" . '_' . time() . "." .$request->file('image')->extension()); + $domain = parse_url(url(""), PHP_URL_HOST); + $domain = $domain == "localhost" ? "example.com" : $domain; + + $user = User::create([ + "name" => "Admin-Created-" . $newNumber, + "email" => strtolower(random_str(8)) . "@" . $domain, + "password" => Hash::make(random_str(32)), + "role" => "user", + "block" => "no", + ]); + + return redirect("admin/edit-user/" . $user->id); + } + + //Delete existing user + public function deleteUser(request $request) + { + $id = $request->id; + + Link::where("user_id", $id)->delete(); + + Schema::disableForeignKeyConstraints(); + + $user = User::find($id); + $user->forceDelete(); + + Schema::enableForeignKeyConstraints(); + + return redirect("admin/users/all"); + } + + //Delete existing user with POST request + public function deleteTableUser(request $request) + { + $id = $request->id; + + Link::where("user_id", $id)->delete(); + + Schema::disableForeignKeyConstraints(); + + $user = User::find($id); + $user->forceDelete(); + + Schema::enableForeignKeyConstraints(); + } + + //Show user to edit + public function showUser(request $request) + { + $id = $request->id; + + $data["user"] = User::where("id", $id)->get(); + + return view("panel/edit-user", $data); + } + + //Show link, click number, up link in links page + public function showLinksUser(request $request) + { + $id = $request->id; + + $data["user"] = User::where("id", $id)->get(); + + $data["links"] = Link::select( + "id", + "link", + "title", + "order", + "click_number", + "up_link", + "links.button_id", + ) + ->where("user_id", $id) + ->orderBy("up_link", "asc") + ->orderBy("order", "asc") + ->paginate(10); + return view("panel/links", $data); + } + + //Delete link + public function deleteLinkUser(request $request) + { + $linkId = $request->id; + + Link::where("id", $linkId)->delete(); + + return back(); + } + + //Save user edit + public function editUser(request $request) + { + $request->validate([ + "name" => "", + "email" => "", + "password" => "", + "littlelink_name" => "", + ]); + + $id = $request->id; + $name = $request->name; + $email = $request->email; + $password = Hash::make($request->password); + $profilePhoto = $request->file("image"); + $littlelink_name = $request->littlelink_name; + $littlelink_description = $request->littlelink_description; + $role = $request->role; + $customBackground = $request->file("background"); + $theme = $request->theme; + + if (User::where("id", $id)->get("role")->first()->role = !$role) { + if ($role == "vip") { + UserData::saveData($id, "checkmark", true); + } + } + + if ($request->password == "") { + User::where("id", $id)->update([ + "name" => $name, + "email" => $email, + "littlelink_name" => $littlelink_name, + "littlelink_description" => $littlelink_description, + "role" => $role, + "theme" => $theme, + ]); + } else { + User::where("id", $id)->update([ + "name" => $name, + "email" => $email, + "password" => $password, + "littlelink_name" => $littlelink_name, + "littlelink_description" => $littlelink_description, + "role" => $role, + "theme" => $theme, + ]); + } + if (!empty($profilePhoto)) { + $profilePhoto->move(base_path("assets/img"), $id . "_" . time() . ".png"); + } + if (!empty($customBackground)) { + $directory = base_path("assets/img/background-img/"); + $files = scandir($directory); + $pathinfo = "error.error"; + foreach ($files as $file) { + if (strpos($file, $id . ".") !== false) { + $pathinfo = $id . "." . 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/"), + $id . "_" . time() . "." . $request->file("background")->extension(), + ); + } + + return redirect("admin/users/all"); + } + + //Show site pages to edit + public function showSitePage() + { + $data["pages"] = Page::select( + "terms", + "privacy", + "contact", + "register", + )->get(); + return view("panel/pages", $data); + } + + //Save site pages + public function editSitePage(request $request) + { + $terms = $request->terms; + $privacy = $request->privacy; + $contact = $request->contact; + $register = $request->register; + + Page::first()->update([ + "terms" => $terms, + "privacy" => $privacy, + "contact" => $contact, + "register" => $register, + ]); + + return back(); + } + + //Show home message for edit + public function showSite() + { + $message = Page::select("home_message")->first(); + return view("panel/site", $message); + } + + //Save home message, logo and favicon + public function editSite(request $request) + { + $message = $request->message; + $logo = $request->file("image"); + $icon = $request->file("icon"); + + Page::first()->update(["home_message" => $message]); + + if (!empty($logo)) { + // Delete existing image + $path = findFile("avatar"); + $path = base_path("/assets/linkstack/images/" . $path); + + // Delete existing image + if (File::exists($path)) { + File::delete($path); + } + + $logo->move( + base_path("/assets/linkstack/images/"), + "avatar" . "_" . time() . "." . $request->file("image")->extension(), + ); + } + + if (!empty($icon)) { + // Delete existing image + $path = findFile("favicon"); + $path = base_path("/assets/linkstack/images/" . $path); + + // Delete existing image + if (File::exists($path)) { + File::delete($path); + } + + $icon->move( + base_path("/assets/linkstack/images/"), + "favicon" . "_" . time() . "." . $request->file("icon")->extension(), + ); + } + return back(); + } + + //Delete avatar + public function delAvatar() + { + $path = findFile("avatar"); + $path = base_path("/assets/linkstack/images/" . $path); + + // Delete existing image + if (File::exists($path)) { + File::delete($path); + } + + return back(); + } + + //Delete favicon + public function delFavicon() + { + // Delete existing image + $path = findFile("favicon"); + $path = base_path("/assets/linkstack/images/" . $path); + + // Delete existing image + if (File::exists($path)) { + File::delete($path); + } + + return back(); + } + + //View footer page: terms + public function pagesTerms(Request $request) + { + $name = "terms"; - if (!empty($icon)) { - // Delete existing image - $path = findFile('favicon'); - $path = base_path('/assets/linkstack/images/'.$path); - - // Delete existing image - if (File::exists($path)) { - File::delete($path); - } - - $icon->move(base_path('/assets/linkstack/images/'), "favicon" . '_' . time() . "." . $request->file('icon')->extension()); - } - return back(); - } - - //Delete avatar - public function delAvatar() - { - $path = findFile('avatar'); - $path = base_path('/assets/linkstack/images/'.$path); - - // Delete existing image - if (File::exists($path)) { - File::delete($path); - } - - return back(); - } - - //Delete favicon - public function delFavicon() - { - // Delete existing image - $path = findFile('favicon'); - $path = base_path('/assets/linkstack/images/'.$path); - - // Delete existing image - if (File::exists($path)) { - File::delete($path); - } - - return back(); + try { + $data["page"] = Page::select($name)->first(); + } catch (Exception $e) { + return abort(404); } - //View footer page: terms - public function pagesTerms(Request $request) - { - $name = "terms"; - - try { - $data['page'] = Page::select($name)->first(); - } catch (Exception $e) { - return abort(404); - } - - return view('pages', ['data' => $data, 'name' => $name]); - } + return view("pages", ["data" => $data, "name" => $name]); + } - //View footer page: privacy - public function pagesPrivacy(Request $request) - { - $name = "privacy"; - - try { - $data['page'] = Page::select($name)->first(); - } catch (Exception $e) { - return abort(404); - } - - return view('pages', ['data' => $data, 'name' => $name]); - } + //View footer page: privacy + public function pagesPrivacy(Request $request) + { + $name = "privacy"; - //View footer page: contact - public function pagesContact(Request $request) - { - $name = "contact"; - - try { - $data['page'] = Page::select($name)->first(); - } catch (Exception $e) { - return abort(404); - } - - return view('pages', ['data' => $data, 'name' => $name]); + try { + $data["page"] = Page::select($name)->first(); + } catch (Exception $e) { + return abort(404); } - //Statistics of the number of clicks and links - public function phpinfo() - { - return view('panel/phpinfo'); - } + return view("pages", ["data" => $data, "name" => $name]); + } - //Shows config file editor page - public function showFileEditor(request $request) - { - return redirect('/admin/config'); - } + //View footer page: contact + public function pagesContact(Request $request) + { + $name = "contact"; - //Saves advanced config - public function editAC(request $request) - { - if ($request->ResetAdvancedConfig == 'RESET_DEFAULTS') { - copy(base_path('storage/templates/advanced-config.php'), base_path('config/advanced-config.php')); - } else { - file_put_contents('config/advanced-config.php', $request->AdvancedConfig); + try { + $data["page"] = Page::select($name)->first(); + } catch (Exception $e) { + return abort(404); + } + + return view("pages", ["data" => $data, "name" => $name]); + } + + //Statistics of the number of clicks and links + public function phpinfo() + { + return view("panel/phpinfo"); + } + + //Shows config file editor page + public function showFileEditor(request $request) + { + return redirect("/admin/config"); + } + + //Saves advanced config + public function editAC(request $request) + { + if ($request->ResetAdvancedConfig == "RESET_DEFAULTS") { + copy( + base_path("storage/templates/advanced-config.php"), + base_path("config/advanced-config.php"), + ); + } else { + file_put_contents("config/advanced-config.php", $request->AdvancedConfig); + } + + return redirect("/admin/config#2"); + } + + //Saves .env config + public function editENV(request $request) + { + $config = $request->altConfig; + + file_put_contents(".env", $config); + + return Redirect("/admin/config?alternative-config"); + } + + //Shows config file editor page + public function showBackups(request $request) + { + return view("/panel/backups"); + } + + //Delete custom theme + public function deleteTheme(request $request) + { + $del = $request->deltheme; + + if (empty($del)) { + echo '"; + } else { + $folderName = base_path() . "/themes/" . $del; + + function removeFolder($folderName) + { + if (File::exists($folderName)) { + File::deleteDirectory($folderName); + return true; } - return redirect('/admin/config#2'); - } - - //Saves .env config - public function editENV(request $request) - { - $config = $request->altConfig; - - file_put_contents('.env', $config); - - return Redirect('/admin/config?alternative-config'); - } - - //Shows config file editor page - public function showBackups(request $request) - { - return view('/panel/backups'); - } - - //Delete custom theme - public function deleteTheme(request $request) - { - - $del = $request->deltheme; - - if (empty($del)) { - echo ''; - } else { - - $folderName = base_path() . '/themes/' . $del; - - - - function removeFolder($folderName) - { - if (File::exists($folderName)) { - File::deleteDirectory($folderName); - return true; - } - - return false; - } - - removeFolder($folderName); - - return Redirect('/admin/theme'); + return false; + } + + removeFolder($folderName); + + return Redirect("/admin/theme"); + } + } + + // Update themes + public function updateThemes() + { + if ($handle = opendir("themes")) { + while (false !== ($entry = readdir($handle))) { + if (file_exists(base_path("themes") . "/" . $entry . "/readme.md")) { + $text = file_get_contents( + base_path("themes") . "/" . $entry . "/readme.md", + ); + $pattern = "/Theme Version:.*/"; + preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE); + if (!count($matches)) { + continue; + } + $verNr = substr($matches[0][0], 15); } - } - - // Update themes - public function updateThemes() - { - - - if ($handle = opendir('themes')) { - while (false !== ($entry = readdir($handle))) { - - if (file_exists(base_path('themes') . '/' . $entry . '/readme.md')) { - $text = file_get_contents(base_path('themes') . '/' . $entry . '/readme.md'); - $pattern = '/Theme Version:.*/'; - preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE); - if (!count($matches)) continue; - $verNr = substr($matches[0][0], 15); + $themeVe = null; + + if ($entry != "." && $entry != "..") { + if (file_exists(base_path("themes") . "/" . $entry . "/readme.md")) { + if ( + !strpos( + file_get_contents( + base_path("themes") . "/" . $entry . "/readme.md", + ), + "Source code:", + ) + ) { + $hasSource = false; + } else { + $hasSource = true; + + $text = file_get_contents( + base_path("themes") . "/" . $entry . "/readme.md", + ); + $pattern = "/Source code:.*/"; + preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE); + $sourceURL = substr($matches[0][0], 13); + + $replaced = str_replace( + "https://github.com/", + "https://raw.githubusercontent.com/", + trim($sourceURL), + ); + $replaced = $replaced . "/main/readme.md"; + + if (strpos($sourceURL, "github.com")) { + ini_set("user_agent", "Mozilla/4.0 (compatible; MSIE 6.0)"); + try { + $textGit = file_get_contents($replaced); + $patternGit = "/Theme Version:.*/"; + preg_match( + $patternGit, + $textGit, + $matches, + PREG_OFFSET_CAPTURE, + ); + $sourceURLGit = substr($matches[0][0], 15); + $Vgitt = "v" . $sourceURLGit; + $verNrv = "v" . $verNr; + } catch (Exception $ex) { + $themeVe = "error"; + $Vgitt = null; + $verNrv = null; } - - $themeVe = NULL; - - if ($entry != "." && $entry != "..") { - if (file_exists(base_path('themes') . '/' . $entry . '/readme.md')) { - if (!strpos(file_get_contents(base_path('themes') . '/' . $entry . '/readme.md'), 'Source code:')) { - $hasSource = false; + if (trim($Vgitt) > trim($verNrv)) { + $fileUrl = + trim($sourceURL) . + "/archive/refs/tags/" . + trim($Vgitt) . + ".zip"; + + file_put_contents( + base_path("themes/theme.zip"), + fopen($fileUrl, "r"), + ); + + $zip = new ZipArchive(); + $zip->open(base_path() . "/themes/theme.zip"); + $zip->extractTo(base_path("themes")); + $zip->close(); + unlink(base_path() . "/themes/theme.zip"); + + $folder = base_path("themes"); + $regex = "/[0-9.-]/"; + $files = scandir($folder); + + foreach ($files as $file) { + if ($file !== "." && $file !== "..") { + if (preg_match($regex, $file)) { + $new_file = preg_replace($regex, "", $file); + File::copyDirectory( + $folder . "/" . $file, + $folder . "/" . $new_file, + ); + $dirname = $folder . "/" . $file; + if (strtoupper(substr(PHP_OS, 0, 3)) === "WIN") { + system( + "rmdir " . escapeshellarg($dirname) . " /s /q", + ); } else { - $hasSource = true; - - $text = file_get_contents(base_path('themes') . '/' . $entry . '/readme.md'); - $pattern = '/Source code:.*/'; - preg_match($pattern, $text, $matches, PREG_OFFSET_CAPTURE); - $sourceURL = substr($matches[0][0], 13); - - $replaced = str_replace("https://github.com/", "https://raw.githubusercontent.com/", trim($sourceURL)); - $replaced = $replaced . "/main/readme.md"; - - if (strpos($sourceURL, 'github.com')) { - - ini_set('user_agent', 'Mozilla/4.0 (compatible; MSIE 6.0)'); - try { - $textGit = file_get_contents($replaced); - $patternGit = '/Theme Version:.*/'; - preg_match($patternGit, $textGit, $matches, PREG_OFFSET_CAPTURE); - $sourceURLGit = substr($matches[0][0], 15); - $Vgitt = 'v' . $sourceURLGit; - $verNrv = 'v' . $verNr; - } catch (Exception $ex) { - $themeVe = "error"; - $Vgitt = NULL; - $verNrv = NULL; - } - - if (trim($Vgitt) > trim($verNrv)) { - - - $fileUrl = trim($sourceURL) . '/archive/refs/tags/' . trim($Vgitt) . '.zip'; - - - file_put_contents(base_path('themes/theme.zip'), fopen($fileUrl, 'r')); - - - $zip = new ZipArchive; - $zip->open(base_path() . '/themes/theme.zip'); - $zip->extractTo(base_path('themes')); - $zip->close(); - unlink(base_path() . '/themes/theme.zip'); - - $folder = base_path('themes'); - $regex = '/[0-9.-]/'; - $files = scandir($folder); - - foreach ($files as $file) { - if ($file !== '.' && $file !== '..') { - if (preg_match($regex, $file)) { - $new_file = preg_replace($regex, '', $file); - File::copyDirectory($folder . '/' . $file, $folder . '/' . $new_file); - $dirname = $folder . '/' . $file; - if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { - system('rmdir ' . escapeshellarg($dirname) . ' /s /q'); - } else { - system("rm -rf " . escapeshellarg($dirname)); - } - } - } - } - } - } + system("rm -rf " . escapeshellarg($dirname)); } + } } + } } + } } + } } - - return Redirect('/studio/theme'); - } - - //Shows config file editor page - public function showConfig(request $request) - { - return view('/panel/config-editor'); - } - - //Shows config file editor page - public function editConfig(request $request) - { - - $type = $request->type; - $entry = $request->entry; - $value = $request->value; - - if($type === "toggle"){ - if($request->toggle != ''){$value = "true";}else{$value = "false";} - if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);} - } elseif($type === "toggle2") { - if($request->toggle != ''){$value = "verified";}else{$value = "auth";} - if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);} - } elseif($type === "text") { - if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, '"' . $value . '"');} - } elseif($type === "debug") { - if($request->toggle != ''){ - if(EnvEditor::keyExists('APP_DEBUG')){EnvEditor::editKey('APP_DEBUG', 'true');} - if(EnvEditor::keyExists('APP_ENV')){EnvEditor::editKey('APP_ENV', 'local');} - if(EnvEditor::keyExists('LOG_LEVEL')){EnvEditor::editKey('LOG_LEVEL', 'debug');} - } else { - if(EnvEditor::keyExists('APP_DEBUG')){EnvEditor::editKey('APP_DEBUG', 'false');} - if(EnvEditor::keyExists('APP_ENV')){EnvEditor::editKey('APP_ENV', 'production');} - if(EnvEditor::keyExists('LOG_LEVEL')){EnvEditor::editKey('LOG_LEVEL', 'error');} - } - } elseif($type === "register") { - if($request->toggle != ''){$register = "true";}else{$register = "false";} - Page::first()->update(['register' => $register]); - } elseif($type === "smtp") { - if($request->toggle != ''){$value = "built-in";}else{$value = "smtp";} - if(EnvEditor::keyExists('MAIL_MAILER')){EnvEditor::editKey('MAIL_MAILER', $value);} - - if(EnvEditor::keyExists('MAIL_HOST')){EnvEditor::editKey('MAIL_HOST', $request->MAIL_HOST);} - if(EnvEditor::keyExists('MAIL_PORT')){EnvEditor::editKey('MAIL_PORT', $request->MAIL_PORT);} - if(EnvEditor::keyExists('MAIL_USERNAME')){EnvEditor::editKey('MAIL_USERNAME', '"' . $request->MAIL_USERNAME . '"');} - if(EnvEditor::keyExists('MAIL_PASSWORD')){EnvEditor::editKey('MAIL_PASSWORD', '"' . $request->MAIL_PASSWORD . '"');} - if(EnvEditor::keyExists('MAIL_ENCRYPTION')){EnvEditor::editKey('MAIL_ENCRYPTION', $request->MAIL_ENCRYPTION);} - if(EnvEditor::keyExists('MAIL_FROM_ADDRESS')){EnvEditor::editKey('MAIL_FROM_ADDRESS', $request->MAIL_FROM_ADDRESS);} - } elseif($type === "homeurl") { - if($request->value == 'default'){$value = "";}else{$value = '"' . $request->value . '"';} - if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);} - } elseif($type === "maintenance") { - if($request->toggle != ''){$value = "true";}else{$value = "false";} - if(file_exists(base_path("storage/MAINTENANCE"))){unlink(base_path("storage/MAINTENANCE"));} - if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);} - } else { - if(EnvEditor::keyExists($entry)){EnvEditor::editKey($entry, $value);} + } + } + + return Redirect("/studio/theme"); + } + + //Shows config file editor page + public function showConfig(request $request) + { + return view("/panel/config-editor"); + } + + //Shows config file editor page + public function editConfig(request $request) + { + $type = $request->type; + $entry = $request->entry; + $value = $request->value; + + if ($type === "toggle") { + if ($request->toggle != "") { + $value = "true"; + } else { + $value = "false"; + } + if (EnvEditor::keyExists($entry)) { + EnvEditor::editKey($entry, $value); + } + } elseif ($type === "toggle2") { + if ($request->toggle != "") { + $value = "verified"; + } else { + $value = "auth"; + } + if (EnvEditor::keyExists($entry)) { + EnvEditor::editKey($entry, $value); + } + } elseif ($type === "text") { + if (EnvEditor::keyExists($entry)) { + EnvEditor::editKey($entry, '"' . $value . '"'); + } + } elseif ($type === "debug") { + if ($request->toggle != "") { + if (EnvEditor::keyExists("APP_DEBUG")) { + EnvEditor::editKey("APP_DEBUG", "true"); } - - - - - return Redirect('/admin/config'); - } - - //Shows theme editor page - public function showThemes(request $request) - { - return view('/panel/theme'); - } - - //Removes impersonation if authenticated - public function authAs(request $request) - { - - $userID = $request->id; - $token = $request->token; - - $user = User::find($userID); - - if($user->remember_token == $token && $request->session()->get('display_auth_nav') === $user->remember_token){ - $user->auth_as = null; - $user->remember_token = null; - $user->save(); - - $request->session()->forget('display_auth_nav'); - - Auth::loginUsingId($userID); - - return redirect('/admin/users/all'); - } else { - Auth::logout(); + if (EnvEditor::keyExists("APP_ENV")) { + EnvEditor::editKey("APP_ENV", "local"); } - + if (EnvEditor::keyExists("LOG_LEVEL")) { + EnvEditor::editKey("LOG_LEVEL", "debug"); + } + } else { + if (EnvEditor::keyExists("APP_DEBUG")) { + EnvEditor::editKey("APP_DEBUG", "false"); + } + if (EnvEditor::keyExists("APP_ENV")) { + EnvEditor::editKey("APP_ENV", "production"); + } + if (EnvEditor::keyExists("LOG_LEVEL")) { + EnvEditor::editKey("LOG_LEVEL", "error"); + } + } + } elseif ($type === "register") { + if ($request->toggle != "") { + $register = "true"; + } else { + $register = "false"; + } + Page::first()->update(["register" => $register]); + } elseif ($type === "smtp") { + if ($request->toggle != "") { + $value = "built-in"; + } else { + $value = "smtp"; + } + if (EnvEditor::keyExists("MAIL_MAILER")) { + EnvEditor::editKey("MAIL_MAILER", $value); + } + + if (EnvEditor::keyExists("MAIL_HOST")) { + EnvEditor::editKey("MAIL_HOST", $request->MAIL_HOST); + } + if (EnvEditor::keyExists("MAIL_PORT")) { + EnvEditor::editKey("MAIL_PORT", $request->MAIL_PORT); + } + if (EnvEditor::keyExists("MAIL_USERNAME")) { + EnvEditor::editKey( + "MAIL_USERNAME", + '"' . $request->MAIL_USERNAME . '"', + ); + } + if (EnvEditor::keyExists("MAIL_PASSWORD")) { + EnvEditor::editKey( + "MAIL_PASSWORD", + '"' . $request->MAIL_PASSWORD . '"', + ); + } + if (EnvEditor::keyExists("MAIL_ENCRYPTION")) { + EnvEditor::editKey("MAIL_ENCRYPTION", $request->MAIL_ENCRYPTION); + } + if (EnvEditor::keyExists("MAIL_FROM_ADDRESS")) { + EnvEditor::editKey("MAIL_FROM_ADDRESS", $request->MAIL_FROM_ADDRESS); + } + } elseif ($type === "homeurl") { + if ($request->value == "default") { + $value = ""; + } else { + $value = '"' . $request->value . '"'; + } + if (EnvEditor::keyExists($entry)) { + EnvEditor::editKey($entry, $value); + } + } elseif ($type === "maintenance") { + if ($request->toggle != "") { + $value = "true"; + } else { + $value = "false"; + } + if (file_exists(base_path("storage/MAINTENANCE"))) { + unlink(base_path("storage/MAINTENANCE")); + } + if (EnvEditor::keyExists($entry)) { + EnvEditor::editKey($entry, $value); + } + } else { + if (EnvEditor::keyExists($entry)) { + EnvEditor::editKey($entry, $value); + } + } + + return Redirect("/admin/config"); + } + + //Shows theme editor page + public function showThemes(request $request) + { + return view("/panel/theme"); + } + + //Removes impersonation if authenticated + public function authAs(Request $request) + { + $userID = $request->id; + $token = $request->token; + + $user = User::find($userID); + + if (!$user) { + Auth::logout(); + return redirect("/login"); + } + + $userRememberToken = $user->remember_token; + $sessionToken = $request->session()->get("display_auth_nav"); + + if ( + !empty($token) && + !empty($userRememberToken) && + !empty($sessionToken) && + hash_equals($userRememberToken, $token) && + hash_equals($userRememberToken, $sessionToken) + ) { + $user->auth_as = null; + $user->remember_token = null; + $user->save(); + + $request->session()->forget("display_auth_nav"); + + Auth::loginUsingId($userID); + + return redirect("/admin/users/all"); + } else { + Auth::logout(); + return redirect("/login"); + } + } + + //Add impersonation + public function authAsID(request $request) + { + $adminUser = User::whereNotNull("auth_as")->where("role", "admin")->first(); + + if (!$adminUser) { + $userID = $request->id; + $id = Auth::user()->id; + + $user = User::find($id); + + $user->auth_as = $userID; + $user->save(); + + return redirect("dashboard"); + } else { + return redirect("admin/users/all"); + } + } + + //Show info about link + public function redirectInfo(request $request) + { + $linkId = $request->id; + + if (empty($linkId)) { + return abort(404); } - //Add impersonation - public function authAsID(request $request) - { - - $adminUser = User::whereNotNull('auth_as')->where('role', 'admin')->first(); - - if (!$adminUser) { - - $userID = $request->id; - $id = Auth::user()->id; - - $user = User::find($id); - - $user->auth_as = $userID; - $user->save(); - - return redirect('dashboard'); - - } else { - return redirect('admin/users/all'); - } + $linkData = Link::find($linkId); + $clicks = $linkData->click_number; + if (empty($linkData)) { + return abort(404); } - //Show info about link - public function redirectInfo(request $request) + function isValidLink($url) { - $linkId = $request->id; + $validPrefixes = ["http", "https", "ftp", "mailto", "tel", "news"]; - if (empty($linkId)) { - return abort(404); - } - - $linkData = Link::find($linkId); - $clicks = $linkData->click_number; - - if (empty($linkData)) { - return abort(404); - } - - function isValidLink($url) { - $validPrefixes = array('http', 'https', 'ftp', 'mailto', 'tel', 'news'); - - $pattern = '/^(' . implode('|', $validPrefixes) . '):/i'; - - if (preg_match($pattern, $url) && strlen($url) <= 155) { - return $url; - } else { - return "N/A"; - } - } - - $link = isValidLink($linkData->link); + $pattern = "/^(" . implode("|", $validPrefixes) . "):/i"; - $userID = $linkData->user_id; - $userData = User::find($userID); + if (preg_match($pattern, $url) && strlen($url) <= 155) { + return $url; + } else { + return "N/A"; + } + } - return view('linkinfo', ['clicks' => $clicks, 'linkID' => $linkId, 'link' => $link, 'id' => $userID, 'userData' => $userData]); + $link = isValidLink($linkData->link); - } + $userID = $linkData->user_id; + $userData = User::find($userID); + return view("linkinfo", [ + "clicks" => $clicks, + "linkID" => $linkId, + "link" => $link, + "id" => $userID, + "userData" => $userData, + ]); + } } diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 3014d810f..d8ce5e07f 100755 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -292,6 +292,9 @@ public function saveLink(Request $request) $filteredLinkData['type_params'] = json_encode($customParams); if ($OrigLink) { + if ($OrigLink->user_id !== $userId) { + abort(403); + } $currentValues = $OrigLink->getAttributes(); $nonNullFilteredLinkData = array_filter($filteredLinkData, function($value) {return !is_null($value);}); $updatedValues = array_merge($currentValues, $nonNullFilteredLinkData); @@ -335,6 +338,7 @@ public function sortLinks(Request $request) $linkNewOrders[$linkId] = $newOrder; Link::where("id", $linkId) + ->where("user_id", Auth::user()->id) ->update([ 'order' => $newOrder ]); @@ -609,6 +613,8 @@ public function editPage(Request $request) $profilePhoto = $request->file('image'); $pageName = $request->littlelink_name; $pageDescription = strip_tags($request->pageDescription, '