1 | <html> |
---|
2 | <head> |
---|
3 | <title>technikum29 Privatbereich -- Projekte-Administration</title> |
---|
4 | <style> |
---|
5 | /* naja, Design will ich das nicht nennen ;) */ |
---|
6 | body { margin: 2em; background-color: #eee; font-family: Arial; font-size: 16px; } |
---|
7 | table td, table th { padding: 10px; } |
---|
8 | table th { font-weight: bold; background-color: #aaa; } |
---|
9 | a:hover { background-color: yellow; } |
---|
10 | pre, label, div.label { display:block; padding: 10px; border: 1px solid #aaa; background-color: #fff; } |
---|
11 | /* allgemeine hervorhebung */ |
---|
12 | em, h2 i { background-color: yellow; } |
---|
13 | </style> |
---|
14 | <link rel="stylesheet" type="text/css" href="/src/private.design/style.css"> |
---|
15 | </head> |
---|
16 | <body> |
---|
17 | <h1><a href="/projekte"><span>technikum29: </span></a><strong>Projekte</strong></h1> |
---|
18 | |
---|
19 | <h2>Adminstation der <a href="/projekte">Projekte</a></h2> |
---|
20 | <?php |
---|
21 | /** |
---|
22 | * Konfigurations-GUI zur Verwaltung des Projekte-Passwortschutzes. |
---|
23 | * Diese GUI erledigt die .htaccess-Dateien pro Verzeichnis sowie |
---|
24 | * die Erstellung der Passwörter, in dem es auf das externe Programm |
---|
25 | * `$htpasswd` zugreift. |
---|
26 | * |
---|
27 | * |
---|
28 | **/ |
---|
29 | |
---|
30 | ///// Konfigurationsvariablen ////// |
---|
31 | |
---|
32 | // Pfad zu htpasswd2 |
---|
33 | $htpasswd = '/usr/bin/htpasswd'; |
---|
34 | |
---|
35 | // die zu bearbeitende .htpasswd-File, Schreib+Lesezugriff nötig |
---|
36 | $passwd_file = '/srv/www/.htpasswd-projekte'; |
---|
37 | |
---|
38 | // das Verzeichnis, in dem sich die Projekt-Ordner befinden, |
---|
39 | // inklusive trailing slash, relativ zum PHP-Script |
---|
40 | $projekte_dir = '../'; |
---|
41 | |
---|
42 | // Verzeichnisse, die bei der Auflistung des Projekt-Ordners |
---|
43 | // nicht angezeigt werden sollen. Angegeben wird ein Regex zur Übergabe |
---|
44 | // an preg_match. Üblicherweise ., .. und Administrationsverzeichnisse |
---|
45 | $exclude_dirs = "/(^\.\.?)|admin/"; |
---|
46 | |
---|
47 | // Template, aus dem sich der Inhalt für die erzeugten .htpasswd- |
---|
48 | // Dateien in den entsprechenden Projekt-Verzeichnissen zusammensetzt. |
---|
49 | // $dir wird dabei später durch den Name des entsprechenden Projekt-Verzeichnisses |
---|
50 | // ersetzt. |
---|
51 | $htpasswd_template = "# automatically generated by technikum29 project administration\nRequire user \$dir admin\n"; |
---|
52 | |
---|
53 | |
---|
54 | /** |
---|
55 | * Einzelne Teilroutinen sind ziemlich genau aus der ersten komplett |
---|
56 | * PHP-basierten Weiterleit-Engine übernommen |
---|
57 | 0 **/ |
---|
58 | // htpasswd einlesen |
---|
59 | $passwd_file_content = file($passwd_file); |
---|
60 | if(!$passwd_file_content) { |
---|
61 | echo "Konnte Passwort-Datei nicht einlesen."; |
---|
62 | exit; |
---|
63 | } |
---|
64 | $registered_dirs = array(); |
---|
65 | foreach($passwd_file_content as $line) { |
---|
66 | if($line{0} == '#') continue; // Kommentare |
---|
67 | if(($x = strpos($line, ':')) !== FALSE) { |
---|
68 | $registered_dirs[] = substr($line, 0, $x); // Nur Name kopieren, nicht pwd |
---|
69 | } |
---|
70 | } |
---|
71 | |
---|
72 | // Allgemeiner Übersichts-Aufruf. |
---|
73 | if(!isset($_GET['dir']) && empty($_POST)) { |
---|
74 | ?> |
---|
75 | |
---|
76 | <p>Übersicht aller vorhandenen Projekt-Verzeichnisse <u>auf dem Server</u>: (<span style="background-color:green;">grün</span> = Passwortgeschützt, <span style="background-color:orange;">orange</span> = momentan für jeden Besucher lesbar)</p> |
---|
77 | |
---|
78 | <div style="float:right; margin-left: 2em; border: 1px solid #aaa; padding: 1em;width:40%;"> |
---|
79 | <h4>Welche Daten ausreichen, um zu einem Projekt zu kommen</h4> |
---|
80 | <p>Der Person, die auf das Projekt <em>beispiel</em> zugreifen soll, |
---|
81 | müssen folgende drei Dinge übermittelt werden:</p> |
---|
82 | <ol> |
---|
83 | <li>Die Adresse der Homepage, <i>www.technikum29.de</i>, wo |
---|
84 | auf die Projekte verlinkt ist</li> |
---|
85 | <li>Den <em>Namen des Projektes</em>, den er in der Liste |
---|
86 | anklickt.</li> |
---|
87 | <li>Ggf. das <em>Passwort</em>, welches für das Projekt |
---|
88 | gesetzt wurde.</li> |
---|
89 | </ol> |
---|
90 | <p>Beim Klick auf den Projektnamen erscheint dann ein Dialogfenster, |
---|
91 | wo der Besucher aufgefordert wird, die Benutzer/Passwort- |
---|
92 | Kombination einzutippen. Bei falschem Benutzer/Passwort erscheint |
---|
93 | eine Fehlernachricht.</p> |
---|
94 | </div> |
---|
95 | |
---|
96 | <table border> |
---|
97 | <?php |
---|
98 | // Verzeichnisse durchgehen |
---|
99 | chdir($projekte_dir); |
---|
100 | if($handle = opendir('.')) { |
---|
101 | while(false !== ($dir = readdir($handle))) { |
---|
102 | if (preg_match($exclude_dirs, $dir) || !is_dir($dir)) continue; |
---|
103 | $has_pwd = in_array($dir, $registered_dirs); |
---|
104 | echo '<tr><th style="background-color:'.($has_pwd?'green':'orange')."\">$dir</th>\t<td><a href=\"${projekte_dir}${dir}\" target=\"_blank\">anschauen</a></td>\t<td><a href=\"?dir=$dir\" title=\"Passwort setzen/veraendern\">"; |
---|
105 | if($has_pwd) { |
---|
106 | echo "Passwort ändern"; |
---|
107 | } else { |
---|
108 | echo "<b>Passwort für Verzeichnis einrichten...</b>"; |
---|
109 | } |
---|
110 | echo "</a></td></tr>\n"; |
---|
111 | } |
---|
112 | closedir($handle); |
---|
113 | } |
---|
114 | ?> |
---|
115 | </table> |
---|
116 | |
---|
117 | <p>Legende zur Benutzung der Tabelle: Durch einen Klick auf <i>anschauen</i> |
---|
118 | werden die Projekt-Ordner in einem neuen Fenster geöffnet. Die Eingabe eines |
---|
119 | Passwortes ist dabei nicht notwendig, da bereits als Administrator angemeldet. |
---|
120 | Ein Klick auf <i>Passwort ändern</i> bzw. <i>Passwort für neues Verzeichnis |
---|
121 | einrichten</i> ändert das Passwort, welches (nur) für dieses Verzeichnis |
---|
122 | gültig ist. Das gesetzte Passwort kann später nicht mehr gelesen werden |
---|
123 | (weil es verschlüsselt gespeichert wird).</p> |
---|
124 | |
---|
125 | <h3>Leitfaden zum Anlegen neuer Projekte</h3> |
---|
126 | |
---|
127 | <p>Die Projekte befinden sich im Unterordner <em>projekte</em> im Homepageverzeichnis. |
---|
128 | Ein einzelnes Projekt entspricht dabei einem Verzeichnis in diesem Unterordner. |
---|
129 | Neue Projekte erstellt man also, in dem man |
---|
130 | ein neues Verzeichnis per Hand erzeugt. In diesem Verzeichnis kann man dann nach |
---|
131 | ohne Beschränkung Dateien erstellen. Anschließend sollte das neue Projekt in der |
---|
132 | HTML-Datei <a href="../index.shtml">index.shtml</a> in der Liste eingetragen werden.</p> |
---|
133 | |
---|
134 | <p>In der (über FTP) runtergeladenen Version der Projekte ist der Passwortschutz |
---|
135 | noch nicht vorhanden. <b>Erst nachdem der neue Projektordner</b> und die geänderte |
---|
136 | <i>index.shtml</i>-Datei per FTP <b>hochgeladen wurden, kann in dieser |
---|
137 | Administrationsoberfläche hier ein Passwort für das neue Projekt eingerichtet |
---|
138 | werden</b>.</p> |
---|
139 | |
---|
140 | <p>Bitte für die <b>Namen von Projekt-Verzeichnissen</b> beachten: Es wird ausdrücklich empfohlen, ausschließlich ein <u>einzelnes, kleingeschriebenes Wort</u> als Projekt/Verzeichnisname zu wählen! Punkte (<tt>.</tt>) und Doppelpunkte (<tt>:</tt>) sind zuzüglich zu den normalen Beschränkungen für Dateinamen nicht erlaubt.</p> |
---|
141 | |
---|
142 | <?php |
---|
143 | } else if(isset($_GET['dir']) && empty($_POST)) { |
---|
144 | // Passwort aendern fuer Verzeichnis "dir" |
---|
145 | chdir($projekte_dir); |
---|
146 | $dir = $_GET['dir']; # $dir muss nicht auf sowas wie ../../passwd überprüft werden, weil |
---|
147 | # hier nu rein Formular aufgesetzt wird |
---|
148 | if(!is_dir($dir)) { |
---|
149 | echo "Gewünschtes Verzeichnis <i>$dir</i> existiert nicht."; |
---|
150 | exit; |
---|
151 | } |
---|
152 | |
---|
153 | $is_new = in_array($dir, $registered_dirs); |
---|
154 | if($is_new) { |
---|
155 | echo "<h2>Passwortschutz für <i>$dir</i> einrichten</h2>\n"; |
---|
156 | echo "<p>Im Folgenden kann ein Passwort festgelegt werden, welches nur für dieses Verzeichnis gelten wird.</p>\n"; |
---|
157 | } else { |
---|
158 | echo "<h2>Neues Passwort für <i>$dir</i> setzen</h2>\n"; |
---|
159 | echo "<p>Das alte Passwort wird dabei durch das neue ersetzt. Zugriffe mit dem alten Passwort sind nicht anschließend nicht mehr möglich. Das neue Passwort tritt umgehend in Kraft.</p>\n"; |
---|
160 | } |
---|
161 | ?><form method="POST"> |
---|
162 | <input type="hidden" name="dir" value="<?=$dir; ?>"> |
---|
163 | <div class="label"> <!--for="source1">--><input type="radio" name="pwd_source" id="source1" value="auto" checked="checked"> Bitte automatisch ein Passwort mit |
---|
164 | <input type="input" name="auto_length" value="8"> Zeichen generieren. |
---|
165 | </div> |
---|
166 | <p><u>oder</u></p> |
---|
167 | <div class="label"><!-- for="source2">--> |
---|
168 | <input type="radio" name="pwd_source" id="source2" value="self"> Das folgende, selbst gewählte Passwort einstellen: |
---|
169 | <input type="password" name="own_pwd"> |
---|
170 | </div> |
---|
171 | |
---|
172 | <p><u>oder</u></p> |
---|
173 | <label for="source3"><input type="radio" name="pwd_source" id="source3" value="delete"> Passwort für dieses Passwort löschen – jeder kann dann den Projektinhalt ohne Passwort erreichen!</label> |
---|
174 | |
---|
175 | <p><input type="submit" value="Passwort setzen"></p> |
---|
176 | </form> |
---|
177 | |
---|
178 | <p>Bitte folgende Hinweise beachten:</p> |
---|
179 | <ul> |
---|
180 | <li>Bei der Erzeugung eines automatischen Passwortes wird dies auf der folgenden Seite in großer |
---|
181 | Schrift angezeigt. Bitte abschreiben!</li> |
---|
182 | <li>Das Passwort wird in jedem Fall verschlüsselt gespeichert. Es handelt sich um eine Einwegverschlüsselung, |
---|
183 | sodass das Klartextpasswort anschließend nicht mehr herausgefunden werden kann!</li> |
---|
184 | </ul> |
---|
185 | <?php |
---|
186 | |
---|
187 | } else if(!empty($_POST)) { |
---|
188 | // Passwortformular ausgefüllt |
---|
189 | if(!($source = $_POST['pwd_source']) || !($dir = $_POST['dir'])) { |
---|
190 | echo "Formular fehlerhaft, Daten fehlen.\n"; |
---|
191 | exit; |
---|
192 | } |
---|
193 | |
---|
194 | // dir gegen hijacking absichern (+ gegen "admin"-Passwort ueberschreiben) |
---|
195 | if(strpos($dir, '/') || $dir == "admin") { |
---|
196 | echo "Keine faulen Tricks."; |
---|
197 | exit; |
---|
198 | } |
---|
199 | |
---|
200 | // in diese Variable wird dann das Passwort gespeichert und anschließend gesetzt. |
---|
201 | $password = false; // wenn am Ende immer noch false, dann Löschen! |
---|
202 | if($source == 'delete') { |
---|
203 | // Passwortschutz (ggf.) löschen! |
---|
204 | $password = false; |
---|
205 | echo "<h2>Passwortschutz für <i>$dir</i> entfernt.</h2>"; |
---|
206 | echo '<p>Der Inhalt des Projektes kann jetzt von jedem im Internet gelesen werden!</p>'; |
---|
207 | } else if($source == 'self') { |
---|
208 | // Gesendetes Passwort übernehmen |
---|
209 | $password = $_POST['own_pwd']; |
---|
210 | if(!$password) { |
---|
211 | echo "<h2>Fehler</h2><p>Und wo ist jetzt das gewünschte Passwort? Wohl vergessen einzutippen. Bitte zurückgehen und nachtragen."; |
---|
212 | exit; |
---|
213 | } |
---|
214 | echo "<h2>Passwort für <i>$dir</i> wurde gespeichert</h2>"; |
---|
215 | } else if($source == 'auto') { |
---|
216 | // Passwort mit entsprechender Länge generieren |
---|
217 | if(!($auto_length = $_POST['auto_length'])) $auto_length = 8; |
---|
218 | if(!is_numeric($auto_length) || $auto_length <= 0) { |
---|
219 | echo "<h2>Fehler</h2><p>Gewünschte Passwortlänge <i>$auto_length</i> ist keine positive Ganzzahl größer Null (sowas wie 1, 2, 3, 4, ...). Bitte <a href=\"javascript:history.go()\">zurück gehen</a> und korrigieren."; |
---|
220 | exit; |
---|
221 | } |
---|
222 | $password = generate_password($auto_length); |
---|
223 | echo "<h2>Password für <i>$dir</i> generiert und gespeichert</h2>"; |
---|
224 | echo "<p>Es wurde ein Passwort mit $auto_length Zeichen generiert. Bitte abschreiben, sonst ist es unwiderbringlich verloren!</p>"; |
---|
225 | echo "<p>Das Passwort lautet:</p>"; |
---|
226 | echo "<dir style=\"padding:3em;text-align:center;border:5px solid red;font-size:1.4em;font-family:monospace\">$password</dir>"; |
---|
227 | } |
---|
228 | // noch so allgemeine Informationen |
---|
229 | if($password) |
---|
230 | echo '<p>Das neue Passwort gilt ab sofort, das ggf. vorher gesetzte alte Passwort wurde bereits mit dem neuen überschrieben und ist nicht mehr zurück zu gewinnen.</p>'; |
---|
231 | else |
---|
232 | echo '<p>Der passwortlose Zugang gilt ab sofort, das ggf. vorher gesetzte alte Passwort wurde bereits gelöscht und ist nicht mehr zurück zu gewinnen.</p>'; |
---|
233 | ?> |
---|
234 | <p><a href="<?=$_SERVER['PHP_SELF'];?>">Zurück zur Projektauflistungs-Übersicht</a></p> |
---|
235 | <hr> |
---|
236 | <h3>Ausführliche Ausgaben:</h3> |
---|
237 | <pre class="box"><?php |
---|
238 | |
---|
239 | // hier beginnt die wirkliche Arbeit. |
---|
240 | $htaccess_file_name = $projekte_dir.$dir.'/.htaccess'; |
---|
241 | if(!is_file($htaccess_file_name) && $password) { |
---|
242 | $htpasswd_template = str_replace('$dir', $dir, $htpasswd_template); |
---|
243 | if(file_put_contents($htaccess_file_name, $htpasswd_template)) { |
---|
244 | echo "* $htaccess_file_name geschrieben mit folgendem Inhalt:\n"; |
---|
245 | echo $htpasswd_template; |
---|
246 | echo "-- Ende htaccess ---\n"; |
---|
247 | } |
---|
248 | } else if(is_file($htaccess_file_name) && !$password) { |
---|
249 | // Passwort löschen - htaccess löschen |
---|
250 | if(unlink($htaccess_file_name)) |
---|
251 | echo "* $htaccess_file_name erfolgreich gelöscht\n"; |
---|
252 | else |
---|
253 | echo "* <b>Fehler: $htaccess_file_name konnte nicht gelöscht werden!</b>\n"; |
---|
254 | } else if(!$password) { |
---|
255 | echo "* $htacces_file_name existierte noch gar nicht - nichts gelöscht\n"; |
---|
256 | } else if($password) { |
---|
257 | echo "* $htaccess_file_name existiert bereits seit ".date("r", filemtime($htaccess_file_name))."\n"; |
---|
258 | } else echo "* <b>Böser Fehler mit der htaccess-Datei $htaccess_file_name, Passwort= $password</b>\n"; |
---|
259 | |
---|
260 | // htpasswd aufrufen |
---|
261 | echo "* Rufe $htpasswd auf, um $passwd_file zu aktualisieren. Ausgaben:\n"; |
---|
262 | |
---|
263 | $dir = escapeshellarg($dir); |
---|
264 | $command = "$htpasswd -b".($password?'':'D')." $passwd_file $dir " . |
---|
265 | ($password ? escapeshellarg($password) : 'dummytext') . // htpasswds komischer Syntax |
---|
266 | ' 2>&1'; |
---|
267 | system($command, $return_value); |
---|
268 | if($return_value) echo "<b>*** Offensichtlich ist Fehler $return_value aufgetreten! *** </b>\nDas Kommando war:\n$command\n"; |
---|
269 | else echo "* htpasswd-Programm offensichtlich ohne Probleme gelaufen.\n"; |
---|
270 | |
---|
271 | ?>* Fertig</pre> |
---|
272 | <p>Im Falle eines Fehlers sind diese Ausgaben für eine Fehlerbetrachtung zwingend notwendig.</p> |
---|
273 | <?php |
---|
274 | } // end main if |
---|
275 | |
---|
276 | // Hilfsfunktionen |
---|
277 | function generate_password($length) { |
---|
278 | // irgendein Algorithmus, findet man per Suchmaschine. |
---|
279 | $range = array_merge(range('0','9'), range('a','z'), range('A','Z'), array('.','_','+')); |
---|
280 | mt_srand((double)microtime()*1000000); |
---|
281 | for ($i = 1; $i <= (count($range)*2); $i++) { |
---|
282 | $swap = mt_rand(0, count($range)-1); |
---|
283 | $tmp = $range[$swap]; |
---|
284 | $range[$swap] = $range[0]; |
---|
285 | $range[0] = $tmp; |
---|
286 | } |
---|
287 | |
---|
288 | return substr(implode('',$range),0,$length); |
---|
289 | } |
---|
290 | ?> |
---|