continue = FAIL => Session-Zwangslogout, Abbruchmeldung und Schlußverarbeitung + Prüfung auf gültigen Loginstatus, inkl. Timeout = OK => continue = FAIL => Authentifizierungsformular, Abbruchmeldung und Schlußverarbeitung + Prüfung auf Wartungsstatus = OK => continue = FAIL => Abbruchmeldung und Schlußverarbeitung + Login = OK => continue = FAIL => Authentifizierungsformular, Abbruchmeldung und Schlußverarbeitung + Verarbeitung der Submit-Aktionen (POST), Anzeige der einzelnen Orga-Formulare */ /* known bugs / todo - Script rennt in einen Loop-of-Death, wenn man auf einen Button klickt, während die Seite (z.B. wegen dem Fahrplan-Editor) noch nicht fertig aufgebaut war -> Session hängt sich auf. Dieses Problem taucht auf webtest.hamburg.ccc.de auf, ist aber lokal (auf Rainers Notebook) nicht reproduzierbar. -> php-Version oder "nur" Config-Problem? (deadlock-timeout?) */ // this script needs following additional server modules for PHP // - Database: (e.g. pgsql) // write HTTP header (anti-cache) header('Expires: Sun, 31 Dec 1989 23:59:59 GMT'); header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: post-check=0, pre-check=0'); header('Pragma: no-cache'); // recall session session_cache_limiter('nocache'); session_cache_expire(1); session_start(); // define general server constants define( "SERVER_SITE_MAINTENANCE", false ); // maintenance state, set to TRUE to lock this page temporarily define( "SERVER_LOCALHOST_IP", "127.0.0.1" ); // localhost IP, which does not need authentication define( "SERVER_PROTOCOL_HTTPS", "HTTPS" ); // HTTPS protocol name // define server file constants define( "SERVER_FILE_TEMPLATE", "template.shtml" ); // template file define( "SERVER_FILE_HEADER", "ssi_site_header.html" ); // SSI file for site header define( "SERVER_FILE_INTRO", "ssi_site_intro.html" ); // SSI file for site intro define( "SERVER_FILE_EXTRO", "ssi_site_extro.html" ); // SSI file for site extro define( "SERVER_FILE_AUTOGEN", "ssi_site_autogen.html" ); // SSI file for site autogeneration warning define( "SERVER_FILE_ANMELDUNGSLISTE", "anmeldung-data/anmeldung.csv" ); // path and file for registered participants // pages of Kassenliste will be printed and can be arranged horizontally // each column contains as much rows as defined by KASSENLISTE_COLUMN_ROWS, after each column of KASSENLISTE_PAGE_COLUMNS a page break will be initiated define( "KASSENLISTE_COLUMN_ROWS", 61 ); // number of rows per page in kassenliste, pages will be printed horizontally define( "KASSENLISTE_PAGE_COLUMNS", 3 ); // number of columns per page in kassenliste, pages will contain those number printed horizontally // define server file constants define( "ORGA_DAYS_BREAKFAST", 3 ); // // define display constants define( "DISPLAY_TEXT_NONE", " " ); define( "DISPLAY_VALUE_SEPARATOR", chr(9)); // define auth constants define( "AUTH_TIMEOUT_MINUTES", 20 ); // idle timeout for login session define( "AUTH_SERVER_PASS", "[Attrakt.Chaos]*9" ); // login password, [todo:] should be outsourced to an external, secured data file // init references to $_SESSION variables ($sxxx) $sbolauthloggedin = & $_SESSION['bolauthloginok']; $sintauthprevtime = & $_SESSION['intauthprevtime']; // init session variables if ( !isset($sbolauthloggedin) ) $sbolauthloggedin = false; if ( !isset($sintauthprevtime) ) $sintauthprevtime = time(); // init references to $_POST variables ($pxxx) $pstrauth = & $_POST['txtauth']; $pbollogin = & $_POST['cmdlogin']; $pbollogout = & $_POST['cmdlogout']; $pbolshowanmeldungen = & $_POST['cmdshowanmeldungen']; $pbolshowkassenliste = & $_POST['cmdshowkassenliste']; // init post variables (only for mandatory variables, ignore variables submitted by special forms!) if ( !isset($pstrauth) ) $pstrauth = ''; // init instance variables $eintritt = array ( 'Normal' => 42, 'Mitglied' => 35, 'Engel' => 35, 'Ermaeszigt' => 35 ); $intnow = time(); $strmsg = ''; // (status/error/etc.) message to user $bolauthabort = false; // auth check will be aborted: show authentication page $bolauthlogoutnow = false; // user will be logged out $strdbfields = array(); $strdbsql = ''; $strdbsql2 = ''; $strdbrow = ''; $strweekdayname = array (1 => 'Sonntag', 2 => 'Montag', 3 => 'Dienstag', 4 => 'Mittwoch', 5 => 'Donnerstag', 6 => 'Freitag', 7 => 'Samstag'); $strvalue = ''; $intindex = 0; $intcolrotate = 1; $strinput = ''; $stroutput = ''; $intfileid = 0; $intcount = 0; $strauth = ''; $bollogin = false; $bollogout = false; $bolshowanmeldungen = false; $bolshowkassenliste = false; $strtablehead = ''; $intcolrot = 0; $boleof = false; $strdbfields = ''; $bolok = false; // action feedback, triggers confirmation if true or warning if false // function library function addmsg ($straddmsg) { // adds $straddmsg to $strmsg global $strmsg; if ( $straddmsg != '' ) { $strmsg = $strmsg . '
  • ' . $straddmsg . '
  • '; } } function showmsg () { // shows messages in $strmsg if available global $strmsg, $bolok; if ( $strmsg != '' ) { echo'

    Feedback

    '; $strmsg = ''; $bolok = false; } } // check input variables //$bollogin = isset( $pbollogin ); // does not work in IE when submitted from within a text field by pressing Return key, reason unknown $bollogin = ( isset( $pbollogin ) || $pstrauth != '' ); //workaround for IE problem, see line above $bollogout = ( isset( $pbollogout ) || $bollogin ); //also fire a logout before (re-)login $bolshowanmeldungen = ( isset( $pbolshowanmeldungen ) ); $bolshowkassenliste = ( isset( $pbolshowkassenliste ) ); // defuse input variables $strauth = trim( htmlentities( $pstrauth, ENT_QUOTES )); // shorten input variables if ( strlen( $strauth ) > 255 ) $strauth = substr( $strauth, 0, 255 ); //cut it, do not modify $strserverremoteaddr = htmlspecialchars( $_SERVER['REMOTE_ADDR'], ENT_QUOTES ); if ( isset( $_SERVER['HTTP_X_FORWARDED_FOR'] )) $strserverremoteaddr = htmlspecialchars( $_SERVER['HTTP_X_FORWARDED_FOR'], ENT_QUOTES ); $strserverprotohttps = htmlspecialchars( $_SERVER['HTTPS'], ENT_QUOTES ); if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] )) $strserverprotohttps = htmlspecialchars( $_SERVER['HTTP_X_FORWARDED_PROTO'], ENT_QUOTES ); // localhost darf immer if ( $strserverremoteaddr != constant("SERVER_LOCALHOST_IP") ) { // check protocol // check secure connection // possible results: // - secure => continue // - insecure => abort processing and show error message ($strmsg) if ( strtolower( $strserverprotohttps ) != 'https' && strtolower( $strserverprotohttps ) != 'on' ) { // insecure connection -> abort if ( !$bolauthlogoutnow && $sbolauthloggedin ) { // active login over insecure connection -> force logout $bolauthlogoutnow = true; addmsg ( 'Du wirst ausgeloggt, da Deine Verbindung unsicher (unverschlüsselt) geworden ist.' ); } addmsg ( 'Dein Verbindungsprotokoll ist HTTP. Bitte verwende für den Orga-Foo Verschlüsselung mittels HTTPS.' ); $bolauthabort = true; $bolok = false; } // check auth timeout // possible results: // - auth active => continue // - auth timeout => force logout ($bolauthlogoutnow), prepare message ($strmsg) and continue if ( $sbolauthloggedin && !$bolauthlogoutnow && ( $intnow > ( $sintauthprevtime + 60 * constant("AUTH_TIMEOUT_MINUTES") ))) { // write message on user authentication expired -> also fire a logout ($bolauthlogoutnow) // echo '
    Du wurdest ausgeloggt wegen mehr als ' . constant("AUTH_TIMEOUT_MINUTES") . ' Minuten Inaktivität.

    '; $bolauthlogoutnow = true; addmsg ( 'Du wirst ausgeloggt wegen mehr als ' . constant("AUTH_TIMEOUT_MINUTES") . ' Minuten Inaktivität.' ); } // restart timeout $sintauthprevtime = $intnow; } else { // localhost ist immer eingeloggt $sbolauthloggedin = true; } if ( $bolauthlogoutnow || $bollogout ) { // logout if ( $bolauthlogoutnow ) { addmsg ( 'Du wurdest automatisch ausgeloggt. Bitte gegebenenfalls erneut einloggen.' ); } $sbolauthloggedin = false; } // check maintenance state if ( constant("SERVER_SITE_MAINTENANCE") ) { // cancel because of maintenance addmsg ( 'Die Orga-Seite ist zurzeit wegen Wartungsarbeiten deaktiviert. Bitte später wiederkommen. Danke.' ); $bolauthabort = true; } // Well, Checkpoint. // Now a defined and normal state of checking has been reached. // Possible states are now: // - $sbolauthloggedin = true: user has successfully authenticated and is still logged in // - $sbolauthloggedin = false: user is either not (yet) authenticated or authentication has been expired // If there were any messages on the way up to here, they are stored as list items (
  • ) in variable $strmsg. // check auth phrase if user tries to login if ( !$bolauthabort && $bollogin && $strauth > '' ) { if ( $strauth == constant("AUTH_SERVER_PASS") ) { // login accepted $sbolauthloggedin = true; } else { // login failed $sbolauthloggedin = false; addmsg ( 'Das klappt so nicht. Vermutlich hast Du Dich vertippt.' ); } } // prepare orga page // assume that all ssi files are there. No, I won't check _that_ explicitely. // If they ain't there, the user gets a partial page. ...so what? ;o) readfile( constant("SERVER_FILE_HEADER") ); echo' Easterhegg - Orga '; readfile( constant("SERVER_FILE_INTRO") ); echo' '; echo '

    interne Orga

    '; // show msg, if available if ( $strmsg != '' ) { echo'

    Authentifizierungshinweis:

      ' . $strmsg . '
    '; $strmsg = ''; } if ( !$sbolauthloggedin ) { // show authentication page and then die if ( !$bolauthabort ) { // show login form echo'

    *knock-knock*

    '; } // close page and stoprun. echo' '; readfile( constant("SERVER_FILE_EXTRO") ); die(); } // Well, Checkpoint. // Now the user is proofed to be successfully logged in. (All others are wiped out.) // From here on the user is authorized to enjoy all the following features. // default sequence within each chapter: // 1. headline // 2. submit action // 3. showmsg(); // 4. user forms // 5. showmsg(); // 6. five empty rows to separate from next chapter ;) // show logout chapter echo'

    Logout

    '; showmsg(); echo '

    '; showmsg(); // show anmeldungen echo'

    Anmeldungen anzeigen

    '; if ( $bolshowanmeldungen ) { // Anmeldungen anzeigen // hmm, das hier musste jetzt mal schnell gehen, schöner oder gar effizienter Code ist das natürlich absolut nicht ;-) $strinput = file_get_contents( constant("SERVER_FILE_ANMELDUNGSLISTE") ); $strinput = htmlentities( $strinput, ENT_QUOTES ); $strinput = str_replace( chr(13), '', $strinput ); $strinput = str_replace( chr(10), '', $strinput ); $strinput = str_replace( chr(9), '', $strinput ); $stroutput = '
    ' . $strinput . '
    '; $stroutput = str_replace( '', '', $stroutput ); $strinput = file( constant("SERVER_FILE_ANMELDUNGSLISTE") ); $intsumanmeldungen = 0; $intsumeinnahmen = 0; $intsumwurst = 0; $intsumkaese = 0; $intsummarmelade = 0; $intsumobst = 0; $intsummuesli = 0; $strangelswithoutgarmentsize = ''; $intsumgarmentsize = array ( '?' => 0, '4XS' => 0, '3XS' => 0, 'XXS' => 0, 'XS' => 0, 'S' => 0, 'M' => 0, 'L' => 0, 'XL' => 0, 'XXL' => 0, '3XL' => 0, '4XL' => 0); foreach ($strinput as $intlinenum => $strline) { if ( $intlinenum != 0 && strlen( $strline ) > 0) { list($strnick, $strstatus, $stremail, $intwurst, $intkaese, $intmarmelade, $intobst, $intmuesli, $strtimestamp, $strgarmentsize) = explode(chr(9), $strline); $intsumanmeldungen = $intsumanmeldungen + 1; $intsumeinnahmen = $intsumeinnahmen + $eintritt[$strstatus]; $intsumwurst = $intsumwurst + $intwurst; $intsumkaese = $intsumkaese + $intkaese; $intsummarmelade = $intsummarmelade + $intmarmelade; $intsumobst = $intsumobst + $intobst; $intsummuesli = $intsummuesli + $intmuesli; $strgarmentsize = trim( $strgarmentsize ); if ( $strgarmentsize != '' ) { if ( array_key_exists( $strgarmentsize, $intsumgarmentsize )) { $intsumgarmentsize[$strgarmentsize] = $intsumgarmentsize[$strgarmentsize] + 1; } elseif( $strgarmentsize > '' ) { $intsumgarmentsize['?'] = $intsumgarmentsize['?'] + 1; } } elseif ( $strstatus == 'Engel' ) { $strangelswithoutgarmentsize = $strangelswithoutgarmentsize . ', "' . $strnick . '"'; } } } $strangelswithoutgarmentsize = substr( $strangelswithoutgarmentsize, 2 ); echo '
    '; echo 'nach Status:'; echo 'Normal: ' . substr_count( $stroutput, '>Normal<' ) . ''; echo 'Mitglieder: ' . substr_count( $stroutput, '>Mitglied<' ) . ''; echo 'Engel: ' . substr_count( $stroutput, '>Engel<' ) . ''; echo 'Ermäßigt: ' . substr_count( $stroutput, '>Ermaeszigt<' ) . ''; echo '
    '; echo 'Gesamt: ' . $intsumanmeldungen . ''; echo 'Einnahmen: ' . $intsumeinnahmen . ' Euro'; echo '
    '; echo '
    '; echo 'nach Futter: pro Tag (' . constant("ORGA_DAYS_BREAKFAST") . ' Tage)'; echo 'Wurst: ' . $intsumwurst . ' (' . ( constant("ORGA_DAYS_BREAKFAST") * $intsumwurst ) . ')' . ''; echo 'Käse: ' . $intsumkaese . ' (' . ( constant("ORGA_DAYS_BREAKFAST") * $intsumkaese ) . ')' . ''; echo 'Marmelade: ' . $intsummarmelade . ' (' . ( constant("ORGA_DAYS_BREAKFAST") * $intsummarmelade ) . ')' . ''; echo 'Obst: ' . $intsumobst . ' (' . ( constant("ORGA_DAYS_BREAKFAST") * $intsumobst ) . ')' . ''; echo 'Müsli: ' . $intsummuesli . ' (' . ( constant("ORGA_DAYS_BREAKFAST") * $intsummuesli ) . ')' . ''; echo '
    '; echo 'Brötchen gesamt: ' . ( $intsumwurst + $intsumkaese + $intsummarmelade ) . ' (' . ( 4 * ( $intsumwurst + $intsumkaese + $intsummarmelade ) ) . ')' . ''; echo '
    '; echo '
    '; echo 'nach Konfektionsgröße:'; foreach ($intsumgarmentsize as $strgarmentsize => $intgarmentsize) { if ( $intgarmentsize > 0 ) echo '' . $strgarmentsize . ': ' . $intgarmentsize . ''; } echo '
    '; echo 'T-Shirts gesamt: ' . ( array_sum( $intsumgarmentsize ) ) . ''; echo 'Engel ohne T-Shirt-Größe: ' . (( $strangelswithoutgarmentsize != '') ? $strangelswithoutgarmentsize : '(keine)' ) . ''; echo '
    '; echo '
    ' . $stroutput . '
    '; } showmsg(); // show kassenliste echo'

    Kassenliste anzeigen

    '; if ( $bolshowkassenliste ) { // Kassenliste anzeigen // hmm, das hier musste jetzt mal schnell gehen, schöner oder gar effizienter Code ist das natürlich absolut nicht ;-) $strinput = file( constant("SERVER_FILE_ANMELDUNGSLISTE") ); array_splice( $strinput, 0, 1 ); // remove first line (header) natcasesort( $strinput ); // sort by nick (first column) $stroutput = ''; $intinputnum = 0; foreach ($strinput as $intlinenum => $strline) { if ( strlen( $strline ) > 0) { $intinputnum = $intinputnum + 1; $bolendofpage = ((($intinputnum % ( constant( "KASSENLISTE_PAGE_COLUMNS" ) * constant( "KASSENLISTE_COLUMN_ROWS" ))) == 0) or ($intinputnum == count($strinput)) ); $bolendofcolumn = ((($intinputnum % constant( "KASSENLISTE_COLUMN_ROWS" )) == 0) or $bolendofpage ); $bolbeginofpage = (($intinputnum % ( constant( "KASSENLISTE_PAGE_COLUMNS" ) * constant( "KASSENLISTE_COLUMN_ROWS" ))) == 1 ); $bolbeginofcolumn = (( $intinputnum % ( constant( "KASSENLISTE_COLUMN_ROWS" )) == 1) or $bolbeginofpage ); list($strnick, $strstatus, $stremail, $intwurst, $intkaese, $intmarmelade, $intobst, $intmuesli, $strtimestamp) = explode(chr(9), $strline); $strnick = htmlentities( $strnick, ENT_QUOTES ); //addmsg($strnick.': '.$intlinenum.'/'.$intinputnum.'='.($bolendofcolumn?'-C':'').($bolendofpage?'-P':'').($bolbeginofpage?'+P':'').($bolbeginofcolumn?'+C':'')); if ( $bolbeginofpage ) { $stroutput = $stroutput . '
    '; } if ( $bolbeginofcolumn ) { $stroutput = $stroutput . ''; } $stroutput = $stroutput . chr(13) . ''; if ( $bolendofcolumn ) { $stroutput = $stroutput . '
    StatusEintrittNick
    ' . $strstatus . '  ' . $eintritt[$strstatus] . '' . $strnick . '
    '; } if ( $bolendofpage ) { $stroutput = $stroutput . '
    '; } } } echo $stroutput; } showmsg(); // close page and stoprun. echo ' '; readfile( constant("SERVER_FILE_EXTRO") ); die(); ?>