Compare commits

...

7 Commits

Author SHA1 Message Date
KodeStar
6b9f61b0e6 Merge pull request #1477 from KodeStar/2.x
Escape search queries and add setting value on edit
2025-07-24 19:06:50 +01:00
Chris Hunt
d1a96dd752 Escape search queries and add setting value on edit 2025-07-24 19:05:16 +01:00
KodeStar
1ccc0da2a7 Merge pull request #1476 from KodeStar/2.x
Load in configs values if class has been lost
2025-07-22 15:59:00 +01:00
Chris Hunt
41aa255b88 Add missing variable 2025-07-22 15:57:29 +01:00
Chris Hunt
a8e4ab448b Load in configs values if class has been lost 2025-07-22 15:50:51 +01:00
KodeStar
e42f78bd49 Merge pull request #1473 from KodeStar/2.x
Add misisng input type in the form builder
2025-07-21 10:12:27 +01:00
Chris Hunt
08b8ab6d4f Add misisng input type in the form builder 2025-07-21 10:10:13 +01:00
9 changed files with 60 additions and 28 deletions

View File

@@ -194,6 +194,7 @@ class ItemController extends Controller
public function create(): View
{
//
$data['item'] = new \App\Item();
$data['tags'] = Item::ofType('tag')->orderBy('title', 'asc')->pluck('title', 'id');
$data['tags']->prepend(__('app.dashboard'), 0);
$data['current_tags'] = '0';
@@ -422,6 +423,7 @@ class ItemController extends Controller
{
$output = [];
$appid = $request->input('app');
$itemId = $request->input('item_id');
if ($appid === 'null') {
return null;
@@ -436,8 +438,10 @@ class ItemController extends Controller
$appdetails = Application::getApp($appid);
if ((bool)$app->enhanced === true) {
$item = $itemId ? Item::find($itemId) : Item::where('appid', $appid)->first();
// if(!isset($app->config)) { // class based config
$output['custom'] = className($appdetails->name) . '.config';
$output['appvalue'] = $item->description;
// }
}

View File

@@ -18,6 +18,9 @@ class SearchController extends Controller
$requestprovider = $request->input('provider');
$query = $request->input('q');
// Sanitize the query to prevent XSS
$query = htmlspecialchars($query, ENT_QUOTES, 'UTF-8');
// Validate the presence and non-emptiness of the query parameter
if (!$query || trim($query) === '') {
abort(400, 'Missing or empty query parameter');

View File

@@ -45,6 +45,7 @@ class SettingsController extends Controller
if (! is_null($setting)) {
return view('settings.edit')->with([
'setting' => $setting,
'value' => $setting->value,
]);
} else {
$route = route('settings.list', []);

View File

@@ -121,7 +121,7 @@ abstract class Search
$output .= '<option value="'.$key.'"'.$selected.'>'.$searchprovider['name'].'</option>';
}
$output .= '</select>';
$output .= '<input type="text" name="q" value="'.(Input::get('q') ?? '').'" class="homesearch" autofocus placeholder="'.__('app.settings.search').'..." />';
$output .= '<input type="text" name="q" value="'.e(Input::get('q') ?? '').'" class="homesearch" autofocus placeholder="'.__('app.settings.search').'..." />';
$output .= '<button type="submit">'.ucwords(__('app.settings.search')).'</button>';
$output .= '</div>';
$output .= '</form>';

View File

@@ -35,5 +35,12 @@ class CustomFormBuilder
);
}
public function input($type, $name, $value = null, $options = [])
{
return new HtmlString(
$this->html->input($type, $name, $value)->attributes($options)
);
}
// Add other methods as needed
}

View File

@@ -150,41 +150,41 @@ class Setting extends Model
switch ($this->type) {
case 'image':
$value = '';
if (isset($this->value) && ! empty($this->value)) {
$value .= '<a class="setting-view-image" href="'.
asset('storage/'.$this->value).
'" title="'.
__('app.settings.view').
'" target="_blank"><img src="'.
asset('storage/'.
$this->value).
if (isset($this->value) && !empty($this->value)) {
$value .= '<a class="setting-view-image" href="' .
asset('storage/' . $this->value) .
'" title="' .
__('app.settings.view') .
'" target="_blank"><img src="' .
asset('storage/' .
$this->value) .
'" /></a>';
}
$value .= '<input type="file" name="value" class="form-control" />';
if (isset($this->value) && ! empty($this->value)) {
$value .= '<a class="settinglink" href="'.
route('settings.clear', $this->id).
'" title="'.
__('app.settings.remove').
'">'.
__('app.settings.reset').
if (isset($this->value) && !empty($this->value)) {
$value .= '<a class="settinglink" href="' .
route('settings.clear', $this->id) .
'" title="' .
__('app.settings.remove') .
'">' .
__('app.settings.reset') .
'</a>';
}
break;
case 'boolean':
$checked = false;
if (isset($this->value) && (bool) $this->value === true) {
if (isset($this->value) && (bool)$this->value === true) {
$checked = true;
}
$set_checked = ($checked) ? ' checked="checked"' : '';
$value = '
<input type="hidden" name="value" value="0" />
<label class="switch">
<input type="checkbox" name="value" value="1"'.$set_checked.' />
<input type="checkbox" name="value" value="1"' . $set_checked . ' />
<span class="slider round"></span>
</label>';
break;
case 'select':
$options = json_decode($this->options);
@@ -193,21 +193,21 @@ class Setting extends Model
}
$value = '<select name="value" class="form-control">';
foreach ($options as $key => $opt) {
$value .= '<option value="'.$key.'" '.(($this->value == $key) ? 'selected' : '').'>'.__($opt).'</option>';
$value .= '<option value="' . $key . '" ' . (($this->value == $key) ? 'selected' : '') . '>' . __($opt) . '</option>';
}
$value .= '</select>';
break;
case 'textarea':
$value = '<textarea name="value" class="form-control" cols="44" rows="15"></textarea>';
$value = '<textarea name="value" class="form-control" cols="44" rows="15">' . htmlspecialchars($this->value, ENT_QUOTES, 'UTF-8') . '</textarea>';
break;
default:
$value = '<input type="text" name="value" class="form-control" />';
$value = '<input type="text" name="value" class="form-control" value="' . htmlspecialchars($this->value, ENT_QUOTES, 'UTF-8') . '" />';
break;
}
return $value;
}
public function group(): BelongsTo
{
return $this->belongsTo(\App\SettingGroup::class, 'group_id');

View File

@@ -5,7 +5,7 @@ use Illuminate\Support\Facades\Facade;
return [
'version' => '2.7.0',
'version' => '2.7.3',
'appsource' => env('APP_SOURCE', 'https://appslist.heimdall.site/'),

View File

@@ -1,6 +1,7 @@
<section class="module-container">
@if($enable_auth_admin_controls)
<header>
{{ html()->hidden('app_id', $item->id) }}
<div class="section-title">{{ __('app.apps.preview') }}</div>
<div class="module-actions">
<div class="toggleinput">
@@ -120,7 +121,7 @@
@if(isset($item) && $item->enhanced())
<div id="sapconfig" style="display: block;">
@if(isset($item))
@if(isset($item) && $item->class)
@include('SupportedApps::'.App\Item::nameFromClass($item->class).'.config')
@endif
</div>

View File

@@ -171,13 +171,14 @@
})
function appload(appvalue) {
const itemId = $('input[name="item_id"]').val();
if(appvalue == 'null') {
$('#sapconfig').html('').hide();
$('#tile-preview .app-icon').attr('src', '/img/heimdall-icon-small.png');
$('#appimage').html("<img src='/img/heimdall-icon-small.png' />");
$('#sapconfig').html('').hide();
} else {
$.post('{{ route('appload') }}', { app: appvalue }, function(data) {
$.post('{{ route('appload') }}', { app: appvalue, item_id: itemId }, function(data) {
// Main details
$('#appimage').html("<img src='"+data.iconview+"' /><input type='hidden' name='icon' value='"+data.iconview+"' />");
$('input[name=colour]').val(data.colour);
@@ -194,6 +195,21 @@
if(data.custom != null) {
$.get(base+'view/'+data.custom, function(getdata) {
$('#sapconfig').html(getdata).show();
// Populate fields in the loaded form with description data
if (data.description) {
const description = JSON.parse(data.appvalue);
Object.keys(description).forEach(function(key) {
const value = description[key];
const field = $(`#sapconfig [name="config[${key}]"]`);
if (field.length) {
if (field.is(':checkbox')) {
field.prop('checked', value);
} else {
field.val(value);
}
}
});
}
});
} else {
$('#sapconfig').html('').hide();