Kalender, Terminliste, Terminformular und Terminzettel laufen ueber db_abfrage() mit Platzhaltern; das Anlegen einer mehrtaegigen Terminreihe liegt in einer Transaktion. Die Logik steckt jetzt in incs/termin.php, sites/termin*.php rufen sie nur noch auf. Dabei behoben: - SQL-Injektion ueber die Suchbegriffe der Terminliste, ueber die Mehrfachauswahl (Ankreuzfelder del<N>/erl<N> gingen roh in DELETE bzw. UPDATE), ueber die Wiedervorlage-Tage (INTERVAL $folgedays DAY) und ueber ?action=terminshow&id=... in maketerminarray(), maketerminadresse(), maketelnrn() und makegooglestring() - gespeichertes XSS: Beschreibung, Notiz, Termintyp, Ort, Kundenname und Mitarbeiterfarbe im Kalender, in der Terminliste und im Formular - "or $err=error(...)" stand innerhalb des Abfrage-Strings, dadurch wurden die Nebenzeilen einer Terminreihe beim Loeschen nie entfernt - die Abfrage zum Folgetermin las eine Spalte typ_id, die es in termin nicht gibt; Typ und Wiedervorlage fehlten deshalb beim Bearbeiten - ein Folgetermin wurde mit termtime='' und termdauer='' angelegt, ein Termin ohne Folgetermin mit followed_by='' - im strikten Modus Fehler - ein Termin ohne Datum landete auf dem 01.01.1970 und gab dabei "NICHTTERMINIERT!!" mitten in die Seite aus - die Ueberschneidungspruefung verglich ab dem zweiten Tag gegen das Ende des ersten Tages - eine unbekannte Registerkarte der Terminliste ergab ein leeres WHERE und damit einen SQL-Fehler; jetzt gilt die Standardansicht - terminshow.php pruefte den Typ mit = statt == - der Kalender haengt nicht mehr an der Locale de_DE (strftime) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
238 lines
8.6 KiB
Smarty
238 lines
8.6 KiB
Smarty
<div class='widthlimiter'>
|
|
{if {$kunde.partner_id}}
|
|
{if $termin.typ == 0}
|
|
{$termin.typ = 1}
|
|
{/if}
|
|
<h2>Termin für Kunde Nummer:</h2>
|
|
<span class='big'>{$kunde.partner_id}</span><br />
|
|
{$kunde.vname|escape} {$kunde.nname|escape} {$kunde.firma|escape}<br />{$kunde.str|escape} {$kunde.hnr|escape}<br />{$kunde.plz|escape} {$kunde.ort|escape}
|
|
{/if}
|
|
{if $user}
|
|
{$termin.user = $user}
|
|
{/if}
|
|
<br />
|
|
<form action="?action=terminadd&formsent=1&adressid={$kunde.id}&id={$termin.id}&user={$user}" name="mainform" method='POST'>
|
|
<fieldset>
|
|
<legend>Termin Informationen:</legend>
|
|
{if {$user} > 0 || (($termin.typ == 0 || $termin.typ == 5 )&& $termin.id > 0)}
|
|
<label>Terminart:</label>
|
|
<select name='typ'>
|
|
{html_options values=$vac_types_id output=$vac_types_name selected="{$termin.typ|default:0}"}
|
|
</select>
|
|
{else}
|
|
<label>Terminart:</label>
|
|
<select name='typ'>
|
|
{html_options values=$typids output=$typs selected="{$termin.typ|default:1}"}
|
|
</select>
|
|
{/if}
|
|
<br />
|
|
<label>Mitarbeiter:</label>
|
|
<select name='user'>
|
|
{html_options values=$optuserids output=$optusers selected="{$termin.user|default:{$smarty.session.user}}"}
|
|
</select><br />
|
|
{if $termin.typ != 0 && $termin.typ != 5}
|
|
<label>Zweiter Mitarbeiter:</label>
|
|
<select name='user2'>
|
|
{html_options values=$optuserids output=$optusers selected="{$termin.user2|default:0}"}
|
|
</select><br />
|
|
<label>Dritter Mitarbeiter:</label>
|
|
<select name='user3'>
|
|
{html_options values=$optuserids output=$optusers selected="{$termin.user3|default:0}"}
|
|
</select><br />
|
|
<label>Vierter Mitarbeiter:</label>
|
|
<select name='user4'>
|
|
{html_options values=$optuserids output=$optusers selected="{$termin.user4|default:0}"}
|
|
</select><br />
|
|
{/if}
|
|
<label>Beschreibung:</label>
|
|
<input name='head' id='head' maxlength='100' value='{$termin.head|escape}' />
|
|
<br />
|
|
<label kundeclass='artlabel'>Notizen:</label>
|
|
<textarea class='bigtextarea' id='text' name='text'>{$termin.text|escape}</textarea><p>
|
|
<label class='checktext'><input type="checkbox" id='done' name="done" value="1" {if $termin.done == 1}checked="checked"{/if} />Termin ist erledigt</label>
|
|
</p>
|
|
<br />
|
|
<p>
|
|
<label id='folgelbl' {if $termin.done == 0}style='color: #ddd;'{/if} class='checktext'><input type="checkbox" id='folge' name="folge" value="1" {if $termin.done == 0}disabled='disabled'{/if}{if $termin.folge == 1}checked="checked"{/if} />Folgetermin vormerken
|
|
</label>
|
|
<br />
|
|
<label id='folgetyplbl' {if $termin.folge == 0}style='color: #ddd;'{/if} class='checktext_align'>
|
|
<select id='folgetyp' name='folgetyp' {if $termin.folge == 0}disabled='disabled'{/if}>
|
|
{html_options values=$typids output=$typs selected="{$termin.folgetyp|default:1}"}
|
|
</select>
|
|
</label><label id='folgedayslbl' {if $termin.folge == 0}style='color: #ddd;'{/if} > in <select id='folgedays' name='folgedays' {if $termin.folge == 0}disabled='disabled'{/if}>
|
|
{html_options values=$days output=$days selected="{$termin.folgedays|default:0}"}
|
|
</select> Tagen</label>
|
|
</p>
|
|
<br />
|
|
<button type="button" class='spell' onclick="$('textarea:not(#personalnotes,#globalnotes),input:not([type=radio])').spellCheckInDialog()">Rechtschreibung prüfen</button>
|
|
</fieldset>
|
|
<fieldset>
|
|
|
|
{if $termin.typ != 0 && $termin.typ != 5}
|
|
<legend>Termin Zeitraum:</legend>
|
|
<label>Von:</label><input name='datetime_start' id='datetime_start' pattern='\d{ldelim}2{rdelim}.\d{ldelim}2{rdelim}.\d{ldelim}4{rdelim}\s\um\s\d{ldelim}2{rdelim}\:\d{ldelim}2{rdelim}' value='{$termin.termtime|mysql_date_to_dispdate}' /><br />
|
|
<label>Bis:</label><input name='datetime_end' id='datetime_end' pattern='\d{ldelim}2{rdelim}.\d{ldelim}2{rdelim}.\d{ldelim}4{rdelim}\s\um\s\d{ldelim}2{rdelim}\:\d{ldelim}2{rdelim}' value='{$termin.termend|mysql_date_to_dispdate}' /><br />
|
|
<button type="button" class='spell' onclick="$('textarea:not(#personalnotes,#globalnotes),input:not([type=radio])').spellCheckInDialog()">Rechtschreibung prüfen</button>
|
|
{else}
|
|
<legend>Urlaubs- / Krankheitszeitraum:</legend>
|
|
<label>Von:</label><input name='datetime_start' id='datetime_start' pattern='\d{ldelim}2{rdelim}.\d{ldelim}2{rdelim}.\d{ldelim}4{rdelim}' value='{$termin.termtime|mysql_date_to_urlaubdispdate}' /><br />
|
|
<label>Bis:</label><input name='datetime_end' id='datetime_end' pattern='\d{ldelim}2{rdelim}.\d{ldelim}2{rdelim}.\d{ldelim}4{rdelim}' value='{$termin.termend|mysql_date_to_urlaubdispdate}' /><br />
|
|
<button type="button" class='spell' onclick="$('textarea:not(#personalnotes,#globalnotes),input:not([type=radio])').spellCheckInDialog()">Rechtschreibung prüfen</button>
|
|
{/if}
|
|
</fieldset>
|
|
<input type='submit' value='Speichern' />
|
|
</form>
|
|
</div>
|
|
|
|
<script>
|
|
$('#done').change(function() {
|
|
|
|
if($('#done:checked').val() == 1)
|
|
{
|
|
$('#folge').removeAttr('disabled');
|
|
$('#folgelbl').removeAttr('style');
|
|
if($('#folge:checked').val() == 1)
|
|
{
|
|
$('#folgedays').removeAttr('disabled');
|
|
$('#folgetyp').removeAttr('disabled');
|
|
$('#folgetyplbl').removeAttr('disabled');
|
|
$('#folgedayslbl').removeAttr('style');
|
|
}
|
|
else
|
|
{
|
|
$('#folgedays').attr('disabled', 'disabled');
|
|
$('#folgetyp').attr('disabled', 'disabled');
|
|
$('#folgetyplbl').attr('disabled', 'disabled');
|
|
$('#folgedayslbl').attr('style', 'color: #ddd;');
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$('#folge').attr('disabled', 'disabled');
|
|
$('#folgedays').attr('disabled', 'disabled');
|
|
$('#folgetyp').attr('disabled', 'disabled');
|
|
$('#folgetyplbl').attr('disabled', 'disabled');
|
|
$('#folgelbl').attr('style', 'color: #ddd;');
|
|
$('#folgedayslbl').attr('style', 'color: #ddd;');
|
|
}
|
|
});
|
|
$('#folge').change(function() {
|
|
|
|
if($('#folge:checked').val() == 1)
|
|
{
|
|
$('#folgedays').removeAttr('disabled');
|
|
$('#folgetyp').removeAttr('disabled');
|
|
$('#folgetyplbl').removeAttr('disabled');
|
|
$('#folgedayslbl').removeAttr('style');
|
|
}
|
|
else
|
|
{
|
|
$('#folgedays').attr('disabled', 'disabled');
|
|
$('#folgetyp').attr('disabled', 'disabled');
|
|
$('#folgedayslbl').attr('style', 'color: #ddd;');
|
|
}
|
|
});
|
|
|
|
{if $termin.typ != 0 && $termin.typ != 5}
|
|
$('#datetime_start').datetimepicker({
|
|
minuteGrid: 15,
|
|
hourGrid: 5,
|
|
stepMinute: 15,
|
|
dateFormat: 'dd.mm.yy',
|
|
timeFormat: 'hh:mm',
|
|
separator: ' um ',
|
|
onClose: function(dateText, inst) {
|
|
var endDateTextBox = $('#datetime_end');
|
|
if (endDateTextBox.val() != '') {
|
|
var testStartDate = new Date(dateText);
|
|
var testEndDate = new Date(endDateTextBox.val());
|
|
if (testStartDate > testEndDate)
|
|
endDateTextBox.val(dateText);
|
|
}
|
|
else {
|
|
endDateTextBox.val(dateText);
|
|
}
|
|
},
|
|
onSelect: function (selectedDateTime){
|
|
var start = $(this).datetimepicker('getDate');
|
|
$('#datetime_end').datetimepicker('option', 'minDate', new Date(start.getTime()));
|
|
}
|
|
});
|
|
$('#datetime_end').datetimepicker({
|
|
minuteGrid: 15,
|
|
hourGrid: 5,
|
|
stepMinute: 15,
|
|
dateFormat: 'dd.mm.yy',
|
|
timeFormat: 'hh:mm',
|
|
separator: ' um ',
|
|
onClose: function(dateText, inst) {
|
|
var startDateTextBox = $('#datetime_start');
|
|
if (startDateTextBox.val() != '') {
|
|
var testStartDate = new Date(startDateTextBox.val());
|
|
var testEndDate = new Date(dateText);
|
|
if (testStartDate > testEndDate)
|
|
startDateTextBox.val(dateText);
|
|
}
|
|
else {
|
|
startDateTextBox.val(dateText);
|
|
}
|
|
},
|
|
onSelect: function (selectedDateTime){
|
|
var end = $(this).datetimepicker('getDate');
|
|
$('#datetime_start').datetimepicker('option', 'maxDate', new Date(end.getTime()) );
|
|
}
|
|
});
|
|
{else}
|
|
$('#datetime_start').datetimepicker({
|
|
minuteGrid: 15,
|
|
hourGrid: 5,
|
|
stepMinute: 15,
|
|
dateFormat: 'dd.mm.yy',
|
|
timeFormat: '',
|
|
separator: '',
|
|
onClose: function(dateText, inst) {
|
|
var endDateTextBox = $('#datetime_end');
|
|
if (endDateTextBox.val() != '') {
|
|
var testStartDate = new Date(dateText);
|
|
var testEndDate = new Date(endDateTextBox.val());
|
|
if (testStartDate > testEndDate)
|
|
endDateTextBox.val(dateText);
|
|
}
|
|
else {
|
|
endDateTextBox.val(dateText);
|
|
}
|
|
},
|
|
onSelect: function (selectedDateTime){
|
|
var start = $(this).datetimepicker('getDate');
|
|
$('#datetime_end').datetimepicker('option', 'minDate', new Date(start.getTime()));
|
|
}
|
|
});
|
|
$('#datetime_end').datetimepicker({
|
|
minuteGrid: 15,
|
|
hourGrid: 5,
|
|
stepMinute: 15,
|
|
dateFormat: 'dd.mm.yy',
|
|
timeFormat: '',
|
|
separator: '',
|
|
onClose: function(dateText, inst) {
|
|
var startDateTextBox = $('#datetime_start');
|
|
if (startDateTextBox.val() != '') {
|
|
var testStartDate = new Date(startDateTextBox.val());
|
|
var testEndDate = new Date(dateText);
|
|
if (testStartDate > testEndDate)
|
|
startDateTextBox.val(dateText);
|
|
}
|
|
else {
|
|
startDateTextBox.val(dateText);
|
|
}
|
|
},
|
|
onSelect: function (selectedDateTime){
|
|
var end = $(this).datetimepicker('getDate');
|
|
$('#datetime_start').datetimepicker('option', 'maxDate', new Date(end.getTime()) );
|
|
}
|
|
});
|
|
|
|
{/if}
|
|
|
|
</script> |