<?php
# CGI-Anfrage: Auflistung des Inhaltes einer .ZIP.Datei

include "zipfile.php";
include 
"unais.php";
include 
"hdump.php";
include 
"oem2utf8.php";
include 
"dxf2svg.php";
include 
"wmf2svg.php";
include 
"eagle2eagle.php";

$DefaultCP="as";    // Automatische Codepage-Ermittlung (bei Textdateien)
$query=array();
$Lang="en";
$ForceLang="";        // Anhängsel an URL zum Retten der Sprache
$_=array();        // Stringtabelle

function SetDefaults() {
 global 
$Lang,$ForceLang,$query,$_;
 if (
strpos($_SERVER['HTTP_ACCEPT_LANGUAGE'],"de")!==false$Lang="de";
 
parse_str($_SERVER["QUERY_STRING"],$query);
 if (
$query["lang"]) {
  
$Lang=$query["lang"];
  
$ForceLang="&lang=".$Lang;    # fortan immer an URL anhängen
 
}
 switch (
$Lang) {
  case 
"de"$_=array(
    
"ASM" => "Assembler-Quelltext (meist 80x86)",
    
"INC" => "Assembler-Include-Datei",
    
"A51" => "Assembler-Quelltext (Keil 8051 oder ASEM51)",
    
"I51" => "Assembler-Include-Datei (Keil 8051 oder ASEM51)",
    
"S51" => "Assembler-Quelltext (Wickenhäuser 8051)",
    
"A90" => "Assembler-Quelltext (Atmel AVR: AT90, ATtiny, ATmega)",
    
"I90" => "Assembler-Include-Datei (Atmel AVR: AT90, ATtiny, ATmega)",
    
"A12" => "Assembler-Quelltext (Microchip PIC 12-bit opcode)",
    
"A14" => "Assembler-Quelltext (Microchip PIC 14-bit opcode)",
    
"A15" => "Assembler-Quelltext (Microchip PIC 14-bit opcode, enhanced)",
    
"A16" => "Assembler-Quelltext (Microchip PIC 16-bit opcode)",
    
"A17" => "Assembler-Quelltext (Microchip PIC 16-bit opcode, enhanced)",
    
"S" => "Assembler-Quelltext (Gnu-C oder gas)",
    
"I16" => "Assembler-Include-Datei (Microchip PIC)",
    
"PAS" => "Pascal-Quelltext",
    
"FRM" => "VisualBasic-Quelltext",
    
"VB" => "VisualBasic-Quelltext",
    
"FRX" => "VisualBasic-Binärformular",
    
"DPR" => "Delphi-Projekt (svw. Quelltext)",
    
"C" => "C-Quelltext",
    
"H" => "Header- oder Kopfdatei für C oder C++",
    
"RC" => "Ressourcendatei (Windows: Menüs, Dialoge usw.)",
    
"CPP" => "C++-Quelltext",
    
"INO" => "Arduino-Projektdatei = C++-Quelltext",
    
"DLL" => "Dynamische Linkbibliothek (Windows)",
    
"386" => "Virtueller Gerätetreiber (Windows 3.x)",
    
"VXD" => "Virtueller Gerätetreiber (Windows 9x)",
    
"CHM" => "Windows-Hilfedatei als kompiliertes HTML",
    
"TTF" => "Windows oder MacOS TrueType-Schrift",
    
"TSV" => "Tab-separierte Wertetabelle",
    
"DRV" => "Gerätetreiber (Windows)",
    
"SYS" => "Gerätetreiber (DOS oder Windows NT)",
    
"COM" => "DOS- oder Z80-Programm",
    
"EXE" => "DOS-, OS/2- oder Windows-Programm",
    
"BAT" => "DOS-Stapel-Programm",
    
"DEB" => "Eingabe für DEBUG",
    
"TXT" => "Textdatei",
    
"HEX" => "Intel-HEX-Datei (Mikrocontroller-Programm)",
    
"EEP" => "Intel-HEX-Datei (Mikrocontroller-EEPROM-Daten)",
    
"IDB" => "Datenbank (Funktionsnamen, Strukturen) zum Intelligenten Disassembler IDA 5",
    
"IIC" => "Binärdaten für seriellen EEPROM",
    
"PKG" => "AIS-Paket-Liste",
    
"TXW" => "KC-WordPro-Textdatei",
    
"M" => "Matlab-Skript",
    
"DSP" => "Visual C++-Projekt",
    
"VCPROJ" => "Visual Studio C++-Projekt",
    
"DSW" => "Visual C++-Arbeitsbereich",
    
"SLN" => "Visual Studio C++-Arbeitsbereich",
    
"MAK" => "MAKE-Datei",
    
"KCC" => "KC85-Maschinenprogramm",
    
"SSS" => "KC85-BASIC-Programm (tokenisiert)",
    
"DIZ" => "Distributions-Beschreibung",
    
"HLP" => "Windows-Hilfe",
    
"RES" => "Binärressource",
    
"LIB" => "Statische Linker-Bibliothek oder DLL-Importbibliothek (DOS/Windows)",
    
"ICO" => "Windows-Symboldatei",
    
"BMP" => "Windows-Bitmap (Bild)",
    
"PS" => "PostScript (Bestückungsdruck?)",
    
"PSZ" => "PostScript, gepackt (Bestückungsdruck?)",
    
"SCH" => "Schaltplan (Eagle oder UltiCap)",
    
"GER" => "PostScript (Schaltplan)",
    
"GEZ" => "PostScript (Schaltplan, gepackt)",
    
"LBR" => "Eagle-Bibliothek",
    
"BRD" => "Eagle-Leiterplatte",
    
"ULP" => "Eagle-Language-Programm",
    
"DDF" => "UltiBoard-Leiterplatte",
    
"FOL" => "PostScript (Leiterplatte)",
    
"FOZ" => "PostScript (Leiterplatte, gepackt)",
    
"GIF" => "Bild (Zeichnung/Screenshot)",
    
"PNG" => "Bild (Zeichnung/Screenshot)",
    
"JPG" => "Bild (Foto)",
    
"MANIFEST" => "Manifest-Datei (Windows XP)",
    
"PDF" => "neumodisches PostScript",
    
"VI" => "LabVIEW-Programmdatei (binär)",
    
"X" => "Linker-Script für gcc",
    
"HTM" => "Hypertext",
    
"WMF" => "16-bit-Vektorgrafik",
    
"EMF" => "32-bit-Vektorgrafik",
    
"DXF" => "CAD-Zeichnung",
    
"CER" => "Zertifikat",
    
"WAV" => "Tonaufnahme",
    
"DMM" => "Plugin-DLL für DMM.EXE",
    
"-f" => "-Datei",
    
"uf" => "Umlaute falsch?",
    
"nk" => "Datei sei UTF-8-kodiert (ohne <b>BOM</b>, typischerweise GCC-Quelletxte)",
    
"ok" => "Datei sei OEM-kodiert (CP437)",
    
"ak" => "Errate Kodierung (entweder OEM oder ANSI; UTF-8 und UTF-16 wird automatisch erkannt)",
    
"ik" => "Errate Kodierung mit inversem Ergebnis",
    
"wk" => "Datei sei ANSI-kodiert (CP1252)",
    
"ec" => "Vorgefundene Kodierung",
    
"ecgi" => "Fehler bei CGI-Anfrage",
    
"msg" => "Meldung",
    
"hack" => "Hack-Versuch abgelehnt!",
    
"con" => "Inhalt von ",
    
"grp" => "\\1.\\2",
    
"n" => "Dateiname",
    
"e" => "Erw",
    
"m" => "Zuletzt geändert",
    
"s" => "Größe",
    
"d" => "Beschreibung",
    
"u" => "(unsortiert)",
    
"v" => "Verzeichnis",
    
"st" => "Starten",
    
"an" => "Ansehen",
    
"ah" => "Anhören",
    
"hw" => "Hineinwechseln",
    
"hl" => "Herunterladen",
    
"da" => "Dateien",
    
"pk" => "In PDF konvertieren und anzeigen",
    
"ub" => "unkomprimierte Bytes",
    
"bom" => "<a href=\"http://de.wikipedia.org/wiki/Byte_Order_Mark\" title=\"Schlag nach bei Wikipedia\">BOM</a>",
    
"sc" => "Skript",
    
"fi" => "Datei",
    
"qt" => "Quelltext",
    
"bd" => "Verzeichnis betrachten, das das Archiv enthält",
    
"zd" => "Archiv (ZIP-Datei) herunterladen",
    
"br" => "Archiv (ZIP-Datei) betrachten",
    
"bz" => "Verzeichnisebene im Archiv betrachten",
    
"cd" => "Das Verzeichnis das Sie gerade hier sehen",
    
"cf" => "Die Datei, die Sie gerade hier sehen, herunterladen",
    
"au" => "[Download]",
    
"mt" => "Sie benötigen eine geeignete Verknüpfung für den MIME-Typ ",
    
"upi" => "Ungültige PATH_INFO!<BR>\n".
    
"(Ein <FONT color=blue>.zip</FONT> muss in der URL enthalten sein!)<BR>\n".
    
"Verwendung: <NOBR><FONT color=blue\n".
    
">/~%s/viewzip.cgi/~<FONT color=green\n".
    
">username/pfad_zum_zip/zipdatei</FONT>.zip/</FONT></NOBR>",
    
"ezip" => "Ungültige oder leere .ZIP-Datei (%s)!</b><br>\n".
          
"Mögliche Ursachen:<UL>\n".
          
"<LI>Pfad nicht korrekt\n".
          
"<LI>Datei gelöscht\n".
          
"<LI>Problem mit Groß/Kleinschreibung\n".
          
"<LI>Problem mit internem Format der .zip-Datei (z.B. defekt)\n".
          
"<LI>Server-Fehler\n".
          
"</UL>\n".
      
"Kommando: <b>„%s“",
    
"foot" => "<i>Generiert durch ein <A href=/~heha/viewzip.phps>".
      
"<B>php</B>-Skript</A></i><p>\n",
  ); break;
  case 
"en"$_=array(
    
"ASM" => "Assembler source (mostly 80x86)",
    
"INC" => "Assembler include file",
    
"A51" => "Assembler source (Keil 8051 or ASEM51)",
    
"I51" => "Assembler Include-Datei (Keil 8051 or ASEM51)",
    
"S51" => "Assembler source (Wickenhäuser 8051)",
    
"A90" => "Assembler source (Atmel AVR: AT90, ATtiny, ATmega)",
    
"I90" => "Assembler include file (Atmel AVR: AT90, ATtiny, ATmega)",
    
"A12" => "Assembler source (Microchip PIC 12-bit opcode)",
    
"A14" => "Assembler source (Microchip PIC 14-bit opcode)",
    
"A15" => "Assembler source (Microchip PIC 14-bit opcode, enhanced)",
    
"A16" => "Assembler source (Microchip PIC 16-bit opcode)",
    
"A17" => "Assembler source (Microchip PIC 16-bit opcode, enhanced)",
    
"S" => "Assembler source (Gnu-C or gas)",
    
"I16" => "Assembler include file (Microchip PIC)",
    
"PAS" => "Pascal source",
    
"FRM" => "VisualBasic source",
    
"VB" => "VisualBasic source",
    
"FRX" => "VisualBasic form",
    
"DPR" => "Delphi project (source)",
    
"C" => "C source",
    
"H" => "C or C++ header file",
    
"RC" => "Resource file (Windows: Menu, dialog etc. definitions)",
    
"CPP" => "C++ source",
    
"INO" => "Arduino project = C++ source",
    
"DLL" => "Dynamic Link library (Windows)",
    
"386" => "Virtual Device Driver (Windows 3.x)",
    
"VXD" => "Virtual Device Driver (Windows 9x)",
    
"CHM" => "Windows Help file as Compiled HTML",
    
"TTF" => "Windows or MacOS TrueType font",
    
"TSV" => "Tab separated values (spreadsheet)",
    
"DRV" => "Device Driver (Windows)",
    
"SYS" => "Device Driver (DOS oder Windows NT)",
    
"COM" => "DOS or Z80 program",
    
"EXE" => "DOS, OS/2, or Windows program",
    
"BAT" => "DOS batch program",
    
"DEB" => "Input for DEBUG",
    
"TXT" => "Text file",
    
"HEX" => "Intel HEX file (microcontroller program)",
    
"EEP" => "Intel HEX file (mikrocontroller EEPROM data)",
    
"IDB" => "Data base (function names, structures) for Intelligent Disassembler IDA 5",
    
"IIC" => "Binary data for serial EEPROM",
    
"PKG" => "AIS packet list",
    
"TXW" => "KC85 WordPro text file",
    
"M" => "Matlab script",
    
"DSP" => "Visual C++ project",
    
"VCPROJ" => "Visual Studio C++ project",
    
"DSW" => "Visual C++ workplace",
    
"SLN" => "Visual Studio C++ workplace",
    
"MAK" => "Makefile",
    
"KCC" => "KC85 machine programm",
    
"SSS" => "KC85 BASIC program (tokenized)",
    
"DIZ" => "Distribution information",
    
"HLP" => "Windows Help",
    
"RES" => "Binary resource",
    
"LIB" => "Static link library or DLL import library (DOS/Windows)",
    
"ICO" => "Windows Icon",
    
"BMP" => "Windows bitmap (image)",
    
"PS" => "PostScript (silkscreen?)",
    
"PSZ" => "PostScript, zipped (silkscreen?)",
    
"SCH" => "Schematic (Eagle or UltiCap)",
    
"GER" => "PostScript (Schematic)",
    
"GEZ" => "PostScript (Schematic, zipped)",
    
"LBR" => "Eagle Electronic Component Library",
    
"BRD" => "Eagle PCB",
    
"ULP" => "Eagle PCB User Language Program",
    
"DDF" => "UltiBoard PCB",
    
"FOL" => "PostScript (PCB)",
    
"FOZ" => "PostScript (PCB, zipped)",
    
"GIF" => "Picture (drawing/screenshot)",
    
"PNG" => "Picture (drawing/screenshot)",
    
"JPG" => "Picture (photographic)",
    
"MANIFEST" => "Manifest file (Windows XP)",
    
"PDF" => "useless PostScript",
    
"VI" => "LabVIEW Virtual Instrument file (binary)",
    
"X" => "Linker script for gcc",
    
"HTM" => "Hypertext",
    
"WMF" => "Windows Meta File (vector graphics)",
    
"EMF" => "Enhanced Meta File (vector graphics)",
    
"DXF" => "CAD drawing",
    
"CER" => "Certificate",
    
"WAV" => "Audio",
    
"DMM" => "Plugin DLL for DMM.EXE",
    
"-f" => " file",
    
"uf" => "Wrong umlauts?",
    
"nk" => "Assume file is UTF-8 encoded (without <b>BOM</b>, mostly GCC source files)",
    
"ok" => "Assume file is OEM (CP437) encoded",
    
"ak" => "Guess file encoding (either OEM or ANSI; UTF-8 and UTF-16 is auto-detected)",
    
"ik" => "Guess file encoding and inverse result",
    
"wk" => "Assume file is ANSI (CP1252) encoded",
    
"ec" => "Detected encoding",
    
"ecgi" => "Erraneous CGI request",
    
"msg" => "Message",
    
"hack" => "Hacking rejected!",
    
"con" => "Content of ",
    
"grp" => "\\1,\\2",
    
"n" => "Filename",
    
"e" => "Ext",
    
"m" => "Last modified",
    
"s" => "Size",
    
"d" => "Description",
    
"u" => "(unsorted)",
    
"v" => "Directory",
    
"st" => "Start",
    
"an" => "View",
    
"ah" => "Listen",
    
"hw" => "Enter subdirectory",
    
"hl" => "Download",
    
"da" => "files",
    
"pk" => "Convert to PDF on-the-fly and show it",
    
"ub" => "uncompressed bytes",
    
"bom" => "<a href=\"http://en.wikipedia.org/wiki/Byte_order_mark\" title=\"Read at Wikipedia\">BOM</a>",
    
"sc" => "Skript file:",
    
"fi" => "File:",
    
"qt" => "Source file:",
    
"bd" => "Browse directory containing archive (zipfile)",
    
"zd" => "Download archive (zipfile)",
    
"br" => "Browse archive (zipfile)",
    
"bz" => "Browse directory level in archive file",
    
"cd" => "The directory level you see here",
    
"cf" => "Download the file you see here",
    
"au" => "[Download]",
    
"mt" => "You need a shell link to MIME type ",
    
"upi" => "Invalid PATH_INFO!<BR>\n".
    
"(A <FONT color=blue>.zip</FONT> string must be in the URL!)<BR>\n".
    
"Usage: <NOBR><FONT color=blue\n".
    
">/~%s/viewzip.cgi/~<FONT color=green\n".
    
">username/path_to_zip/zipfile</FONT>.zip/</FONT></NOBR>",
    
"ezip" => "Invalid or empty .ZIP file (%s)!<BR>\n".
          
"Possible reasons:<UL>\n".
          
" <LI>Path incorrect\n".
          
" <LI>File deleted\n".
          
" <LI>Problem with small/capital letters\n".
          
" <LI>Problem with internal zip file format (e.g. defective)\n".
          
" <LI>Server Bug\n".
          
"</UL>\n".
      
"Command: <b>“%s”",
    
"foot" => "<i>Generated by a <A href=/~heha/viewzip.phps>".
      
"<B>php</B> script</A></i><p>\n",
  ); break;
 }
}

function 
s($s1) {
 global 
$_;
 return 
$_[$s1];
}

function 
Desc($n) {
 global 
$_;
 if (
substr($n,-1)=='/') return $_['v'];
 
$n=mb_strtoupper($n);
 if (
$n == "MAKEFILE"$n "MAK";
 else{
  
$i=strrpos($n,'.');
  if (
$i!==false$n=substr($n,$i+1);
  if (
$n=="HTML"$n="HTM";
 }
 
$d=$_[$n];
 if (
$d) return $d;    // hübsche Beschreibung
 
return $n.$_['-f'];    // <ext>-Datei
}

$mimetype="";

function 
guck($s) {
# ermittelt anhand des Dateinamens s den nötigen Betrachter-Typ
 
global $mimetype;
 
$mimetype="";
 
$s=strtoupper(basename($s));    // basename = Dateiname.Ext, sonst pathinfo() benutzen!
 
if ($s == "MAKEFILE") return "MAK";
 if (
preg_match('/^(README|LIESMICH|DIRINFO|FILELIST)$/',$s))        return "TXT";
 
$i=strrpos($s,'.');
 if (
$i!==false$s=substr($s,$i+1);
 if (
preg_match('/^(ASM|INC|[AI][0-9]{2}|S)$/',$s))            return $s;
 if (
preg_match('/^(PAS|DPR)$/',$s))                    return "PAS";
 if (
preg_match('/^(BAS|FRM|VB)$/',$s))                    return "BAS";
 if (
preg_match('/^(C|RC|JS)$/',$s))                    return "C";
 if (
preg_match('/^(CPP|CC|CXX|C\+\+|H|X|JAVA|INO)$/',$s))        return "CPP";
 if (
preg_match('/^(TXT|PKG|DOC|DIZ|LST|DEB)$/',$s))            return "TXT";
 if (
preg_match('/^(MANIFEST|VCPROJ|HHC|HHK|CSS)$/',$s))        return "XML";
 if (
$s=="DDF")                                return "ULT";
 if (
$s=="TSV")                                return "TSV";
 if (
preg_match('/^(SCH|BRD|LBR|WMF|EMF|DXF)$/',$s))            return "SVG";
 if (
preg_match('/^(MAK|DSP|DSW|SLN)$/',$s))                return "MAK";
 if (
preg_match('/^(HPJ|HHP|INI|INF|REG)$/',$s))            return "INI";
 if (
preg_match('/^(HEX|EEP)$/',$s))                     return "HEX";
 if (
preg_match('/^(COM|EXE|DLL|DRV|SYS|VXD|386|TBL|FRX|CER|VI|LLB|CLASS|ELF)$/',$s)) return "X";
 if (
preg_match('/^(PS|PSZ|GER|GEZ|FOL|FOZ)$/',$s)) {$mimetype="application/postscript"; return "PS";}
 if (
preg_match('/^HTML?$/',$s)){$mimetype="text/html";        return "HTM";}
 if (
$s == "HLP") {$mimetype="application/x-ms-winhelp";        return "HLP";}
 if (
$s == "RES") {$mimetype="application/x-resource-workshop";    return "RES";}
 if (
$s == "AWK")    return "AWK";
 if (
$s == "TXW")    return "TXW";
 if (
$s == "ULP")     return "ULP";
 if (
$s == "DEF")     return "DEF";
 if (
$s == "WRL")     return "WRL";
 if (
$s == "BAT")     return "BAT";
 if (
$s == "M")       return "MAT";
 if (
$s == "ICO")     return "ICO";
 if (
$s == "PCX")     return "PCX";
 if (
$s == "GIF")     return "GIF";
 if (
$s == "PNG")     return "PNG";
 if (
$s == "JPG")     return "JPG";
 if (
$s == "WAV")     return "WAV";
 return 
"";
}

// Listing-Modus: ungenutzt (Sortierung erfolgt durch JavaScript)
// Datei-Modus: Umkodierung ("ansi", "oem" usw.) sonst "bin"
$sort="";

// Listing-Modus: ungenutzt
// Datei-Modus: Textinterpretation (Syntaxparser), Binärinterpretation (ico2gif usw.), Hexdump ("X"), Pixeldump ("P")
$such="";

function 
grouped($z) {
#Wandelt Zahl z in String um und fügt "." in Dreiergruppen ein
 
global $Lang;
 
$z=number_format($z);
 if (
$Lang=="de"$z=str_replace(',','.',$z);
 return 
$z;
}

function 
Fehler($s) {
# Fehler (als richtiges text/html) zum Client ausgeben und Programmende
 
header("Content-type: text/html; charset=utf-8\n\n");
 
printf("<!DOCTYPE html>\n<HTML><HEAD>\n<TITLE>%s</TITLE>\n</HEAD>\n<BODY>\n\n",s("ecgi"));
 
printf("<H1>%s</H1>\n",s("ecgi"));
 
printf("%s: <B>%s</B><P>\n",s("msg"),$s);
 
printf("</BODY></HTML>\n");
 exit(
1);
}

function 
Esc($s) {
 return 
rawurlencode($s);
}

function 
AnsiName($s) {    # QUIRKS: Meistens ist '?' ein ANSI-'ü'
 
$s=preg_replace('/\?\?/',"?",$s);    # QUIRKS: Ist schon UTF-8
 
$s=preg_replace('/er\?t/',"erät",$s);        # QUIRKS (Gerät)
 
$s=preg_replace('/\?bersicht/',"Übersicht",$s);    # QUIRKS
 
$s=preg_replace('/dmm \?/',"dmm β",$s);        # QUIRKS
 
$s=preg_replace('/\?/',"ü",$s);            # QUIRKS
 
return $s;
}

function 
OutUrl($file,$trail) {
# ZIP-Datei als ganzes zum Downloaden anbieten,
# sowie Links zu den enthaltenden Verzeichnissen
# sowie einen Link zum Browsen der ZIP-Datei (wenn das nicht gerade angezeigt wird)
# $file: bspw. "/hs/ADC9834.zip" oder "/~ygu/template/sowas.zip"
# $trail: bspw. "src/note.txt" oder "src/"
 
global $ForceLang;
 if (
substr($file,1,1)!='~'$file=$_SERVER['CONTEXT_PREFIX'].$file;
 echo 
"/";
 
$t="/";
 
$urls=explode("/",substr($file,1));    # führendes "/" entfernen und Pfadelemente ermitteln
 
$last=array_pop($urls);
 foreach (
$urls as $elem) {
  
$t.=Esc($elem)."/";        # Stück für Stück zusammensetzen
  
echo "<A\n\thref=\"$t\" title=\"".s("bd")."\">$elem</A>/";
 }
 
$t.=Esc($last);
//Download-Icon            # ohne Slash!
 
echo "<A\n\thref=\"$t\" title=\"".s("zd")."\"><img src=\"icons/dl.gif\" border=0 align=top alt=\"".s("au")."\"></A>";
 
$t.='/';            # mit Slash!
 
$inspos=strpos($t,'/',1);    # über ~heha drüberweg
 
$t=substr_replace($t,$_SERVER["SCRIPT_NAME"],0,$inspos);    # "viewzip.php" einbauen
 
if ($trail) {
  echo 
"<A\n\thref=\"$t";
  if (
$ForceLang) echo "?$ForceLang";
  echo 
"\" title=\"".s("br")."\">$last</A>";
 }else{
  echo 
"<u title=\"".s("cd")."\">$last</u>";
 }
 echo 
"/";
 
 if (
$trail) {
  
$urls=explode("/",$trail);
  if (
substr($trail,-1)=='/'array_pop($urls);    # $urls-Array "korrigieren"
  
$last=array_pop($urls);
  foreach (
$urls as $elem) {
   
$t.=Esc($elem)."/";        # Stück für Stück zusammensetzen
   
echo "<A\n\thref=\"$t";
   if (
$ForceLang) echo "?$ForceLang";
   echo 
"\" title=\"".s("bz")."\">$elem</A>/";
  }
  
$t.=Esc($last);
  if (
substr($trail,-1)=='/') echo "<u title=\"".s("cd")."\">$last</u>/";
  else{
   echo 
"<A\n\thref=\"$t\" title=\"".s("cf")."\">$last</A>";
  }
 }
}

# Radiobutton ausgeben
function Radio($convcode,$strcode) {
 global 
$trail,$sort,$such,$ForceLang;
 
$fname=basename($trail);
 
$s=$sort$n="";
 if (
substr($s,-1)=='n') {
  
$n=substr($s,-1);
  
$s=substr($s,0,-1);
 }
 if (
$s==$convcode) {
  echo 
"<INPUT type=radio checked>";
  echo 
s($strcode);
 }else{ 
  echo 
"<label><INPUT type=radio onClick=\"self.location.href='$fname?$convcode$n=$such$ForceLang'\">";
  echo 
s($strcode);
  echo 
"</label>";
 }
 echo 
"<br>\n";
}

$linecount=0;

# Checkbox (Zeilennummern) ausgeben nee!
#function CheckLn() {
# global $linecount,$trail,$sort,$such,$ForceLang;
# $fname=basename($trail);
# echo "<label title='Alt+Shift+N'><input type=checkbox accesskey='n' ";
# if ($linecount) echo "checked ";
# $s=$linecount?substr($sort,0,-1):$sort.'n';
# echo "onclick=\"self.location.href='$fname?$s=$such$ForceLang'\">";
# echo s('ln');
# echo "</label>\n";
#}

# Link (Hex/Pixeldump) ausgeben
function HexPix() {
 global 
$trail,$sort,$such,$ForceLang;
 
$fname=basename($trail);
 
$nsort $sort=="P" "X""P";
 
$text $nsort=="P" "Pixeldump" "Hexdump";
 echo 
"<a href=\"$fname?$nsort=$such$ForceLang\">$text</a>\n";
}
     
################################################################
# Syntax-Hervorhebungen: keine! Macht das JavaScript-Programm! #
################################################################

$filectime="2016-01-01";    // Inode-Zeit des Archivs
$filemtime=0;            // Modifikationszeit des Archivs oder der Datei innerhalb dessen

// u.a. Ausgabe der Sprachalternativen (hier nur eine)
function OutHtmlHeader($title,$robots) {
 global 
$Lang,$FirstQuery,$filectime;
 
$q=$FirstQuery;
 if (
$q$q.='&';
 
$languages=Array("de","en");

 echo 
"<!DOCTYPE html>\n";
 echo 
"<html lang=$Lang><head>\n";
 echo 
"<meta name=date content=\"$filectime\">\n";
 if (
$robots) echo "<meta name=robots content=\"$robots\">\n";
 foreach(
$languages as $language) if ($language!=$Lang
   echo 
"<link rel=alternate href='?{$q}lang=$language' lang=$language>\n";
 echo 
"<link rel=stylesheet href='h.css'>\n";
 echo 
"<script src='h.js'></script>\n";
 echo 
"<title>$title</title>\n";
 echo 
"</head>";
}

// liefert ausgepackten Dateiinhalt als Binärstring und setzt die globale Variable $filemtime
function unzip($file,$trail) {
 global 
$filemtime;
 
$dir=list_zip($file);
 
$i=0;
 foreach (
$dir as $e) {
  if (
$e['name']==$trail) break;
  
$i++;
 }
 
$filemtime=$e['time'];
 
$zip=new ZipArchive();
 
$zip->open($file);
 return 
$zip->getFromIndex($i);
}

 
#################
# Hauptprogramm #
#################

$oemdetect=0;

SetDefaults();
$info=$_SERVER["PATH_INFO"];
// Bugbug: Normalerweise sollte Pfadkomponente für Pfadkomponente auf Verzeichnis
// untersucht werden. Wenn Datei, dann Archiv (auch .CHM) annehmen.
// Bei regulärer Datei (Nicht-Archiv) Hände hoch und Redirect ohne viewzip.php
// (Oder Syntaxhervorhebung?)
// Bei weiteren Zip-Dateien (Zip-im-Zip) ganz auspacken und weitermachen (wie auch immer)
$i=strpos($info,".zip/");        # Wo die Datei-Inhalte beginnen
if (!$i$i=strpos($info,".jar/");
if (!
$i) {
 
$i=strpos($info,".exe/");
 if (
$i$ais_mode=true;
}
if (
$i) {
 
$trail=substr($info,$i+5);        # Wenn (trail), dann Datei auspacken!
 
$info=substr($info,0,$i+4);
}else if (
substr($info,-4)==".zip") {
 
$url="http://".$_SERVER["SERVER_NAME"];
 
$port=$_SERVER["SERVER_PORT"];
 if (
$port!=80$url.=":".$port;
 
$url.=$_SERVER["REQUEST_URI"]."/";
 
header("Location: $url");        # Umleitung
 
exit(0);
}else{
 
Fehler($_['upi'].$DefaultPath);
}
if (
$_SERVER['CONTEXT_PREFIX']) {    # Uni
 
$file=$info;                # kommt mit führendem /
 
if (substr($file,0,2)=='/~') {        # Datei anderer User (auf www-user.tu-chemnitz.de)?
  
$i=strpos($file,'/',2);
  if (
$i!==false) {
   
$user=substr($file,1,$i);
   
$file=substr($file,$i);        # vom Anfang entfernen
   
$other='/'.substr($user,1,1).'/'.substr($user,1).'/';    # hier: universitätsspezifisch umbauen
  
}
 }
 
$file=$_SERVER['CONTEXT_DOCUMENT_ROOT'].$file;
 if (
$other) {
  
$file=str_replace('/h/heha/',$other,$file);
 }
}else{                    
# 000webhost
 
$file=substr($info,1);
}
#Das erste Paar heraussuchen
# bspw. "?as=SVG&lang=en" wird zu $sort=="as" und $such=="SVG"
foreach ($query as $sort => $such) {    # $sort = siehe oben
 
break;
}
# prelink=gensub(/^.*\//,"",1,trail);    # bei jedem Link davorzusetzen...

$binaries=array(
    
"ICO",
    
"PCX",
    
"BMP",
    
"GIF",
    
"PNG",
    
"JPG",
    
"WMF",
    
"DXF",
    
"ULT",
    
"WAV",
    
"MP3",
    
"COM",
    
"EXE",
    
"DLL",
    
"DRV",
    
"SYS",
    
"VXD",
    
"386",
    
"TBL",
    
"FRX",
    
"CER",
    
"VI" ,
    
"LLB",
    
"CLASS",
    
"ELF",
    
"HLP",
    
"CHM",
    
"DOC",
    
"XLS",
    
"RES",
    
"PDF",
    
"PDFR",
    
"PS" ,
    
"PSZ",
    
"GER",
    
"GEZ",
    
"FOL",
    
"FOZ",
    
"ZIP",
    
"JAR",
    
"HTM",
    
"HTML",
);

if (
$trail && substr($trail,-1)!='/') {
# Auspack-Modus (Einzeldatei)
 
$data=$ais_mode?unzip_ais($file,$trail):unzip($file,$trail);
 if (
$sort) {
 
# Auspacken mit Anguck-Filter
  
switch ($such) {
   case 
"X": {    # Hexdump
    
ob_start();
    
hdump($data,$sort);
    
$data=ob_get_contents();
    
ob_end_clean();
   }break;
   case 
"P": {    # Pixel-Dump (Optionen in suche[0])
    
$data=base64_encode(pdump($data,$sort));
   }break;
   case 
"ICO"$data=ico2gif($data); break;
   case 
"SVG": {
    
ob_start();
    switch (
strtolower(substr($trail,-3))) {
     case 
"dxf"dxf2svg($data); break;
     case 
"wmf"wmf2svg($data); break;
     case 
"emf"emf2svg($data); break;
     case 
"sch":
     case 
"brd":
     case 
"lbr": {
      
$t=$filemtime;
      if (
$t$t=date("Y-m-d H:i:s",$t);
      
eagle2eagle($data,pathinfo($trail,PATHINFO_FILENAME),$t);
     }break;
    }
    
$data=ob_get_contents();
    
ob_end_clean();
    
$content="image/svg+xml";
   }break;
   case 
"WRL"$content="model/vrml"; break;
   case 
"PCX"$data=pcx2gif($data); break;
   case 
"PDFR"$data=ps2pdf_rotate($data); break;
//   $kdo.=" | sed -e 's/scale/scale -90 rotate -9000 0 translate/'";    #rechts rotieren (nur UltiCAP)
//   $kdo.=" | gs -dQUIET -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -r600 -g7010x4950 -sOutputFile=- - 2>&1";
   
case "PDF"$data=ps2pdf($data); break;
//   $kdo.=" | gs -dQUIET -dBATCH -dNOPAUSE -sDEVICE=pdfwrite -sOutputFile=- - 2>&1";
   
default:
   if (
substr($sort,0,3)=="oem"$oemdetect=1;
   if (
substr($sort,0,2)=="as"$oemdetect=2;
   if (
substr($sort,0,2)=="ai"$oemdetect=3;
   if (
substr($sort,0,4)=="ansi"$oemdetect=4;
   
oem2utf8($data,$oemdetect);
   if (
substr($sort,-1)=="n") {
    
$linecount 1;
   }
  }
  if (!
$content$content=mime_content_type("datei.".strtolower($such));
  if (
$sort!="bin" && !$content) {
   
header("Content-type: text/html; charset=utf-8");
   
$texttyp=s("qt");
   if (
$such == "BAT" || $such == "MAT" || $such == "MAK"$texttyp=s("sc");
   if (
$such == "INI" || $such == "TXT"$texttyp=s("fi");
   if (
$such == "X"$texttyp="Hexdump";
   if (
$such == "P"$texttyp="Pixeldump";
   
OutHtmlHeader($texttyp." ".$trail,$such=="X"||$suche[2]=="P"?"noindex":null);
   echo 
"<BODY";
   if (
$such == "PAS" || $such == "C" || $such == "CPP" || $such == "ASM") {
    
printf(" link=#004000 vlink=#004000");
   }
   echo 
">\n";
//   echo "<div style='background:#F0F0F0'>\n";
   
echo "<h1><small>$texttyp ";
   
OutUrl($info,$trail);
   echo 
"</small></h1>\n";
   if (
$such == "X" || $such == "P"HexPix();
#   else CheckLn();
//   echo "</div>\n";

   
if ($such == "P") {
    print(
"<p style='background:#F0F0F0;padding:8px'><img src='data:image/gif;base64,");
#     print("' height=768 style='image-rendering:pixelated'>");
    
print("'>");
    print(
"</p>");
   }else{
    
$data=str_replace(array("&","<",">"),array("&amp;","&lt;","&gt;"),$data);
    if (
$such=="TSV") {    # als sortierbare Tabelle ausgeben (später evtl. bei langen Zahlenkolonnen als Graf!)
     
echo "<p><table border class='sortable list'>\n";
     
$a=explode("\n",$data);
     foreach (
$a as $line) if ($line) {
      if (
substr($line,-1)=="\r"$line=substr($line,0,-1);
      
$b=explode("\t",$line);
      if (!
$tbody) echo "<thead>";
      echo 
"<tr>";
      if (
$linecount) {
       if (
$tbody) {
    echo 
"<td>";
        echo 
$linecount;
        
$linecount++;
       }else{
        echo 
"<th class=sorted>Zeile";
       }
      }
      foreach (
$b as $cell) {
       echo 
$tbody?"<td>":"<th>";
       echo 
$cell;
      }
      if (!
$tbody) echo "</thead>";
      echo 
"\n";
      
$tbody=true;
     }
     echo 
"</table></p>\n";
    }else{
     echo 
"<pre class=".strtolower($such).">";
     if (
$linecount) {
      
$a=explode("\n",$data);
      foreach (
$a as $line) {
       
printf("<span class=\"ln\" id=%d>%6d </span> %s\n",$linecount,$linecount,$line);
       
$linecount++;
      }
      unset(
$a);
     }else echo 
$data;
     echo 
"</pre>\n";
    }
    unset(
$data);
   }
# Vorgefundene Kodierung ausgeben
   
if (!preg_match('/^(P|HEX|TXW)$/',$such)) {
    echo 
"<TABLE width=100% bgcolor=#F0F0F0><TR><TD>";
    if (
strpos($sort,"as")==|| strpos($sort,"ai")==0) {
     if (
$oemdetect==-3$ko="UTF-16LE + ".s("bom");
     elseif (
$oemdetect==-2$ko="UTF-16LE";
     elseif (
$oemdetect==-1$ko="UTF-8 + ".s("bom");
     elseif (
$oemdetect==0)  $ko="UTF-8";
     elseif (
$oemdetect==1)  $ko="OEM (CP437)";
     elseif (
$oemdetect==4)  $ko="ANSI (CP1252)";
     else 
$ko="ASCII (7 bit)";
     
printf("%s: %s<TD align=right>%d\n",
       
s("ec"),$ko,$oemdetect);
    }
    if (
$oemdetect==|| $oemdetect==4) {
     
printf(" <tr><td><TABLE cellpadding=2 cellspacing=0><TR valign=top><td>%s - <td>\n",s("uf"));    # Tabelle-in-Tabelle
#     Radio("none","nk");
#     Radio("oem", "ok");
     
Radio("as","wk");    # "ak"
     
Radio("ai","ok");    # "ik"
#     Radio("ansi","wk");
#     print ("<td> <img src=\"icons/wikipedia.png\" align=top alt=\"\"> " s("bom"));
#TODO: Datei-Datum und aktuelles Datum ausspucken (letzteres um Kopien von Suchmaschinen zu detektieren)
     
echo " </TABLE>\n";
    }
    echo 
"</TABLE>\n";
   }
   echo 
"</body></html>\n";
   exit;
  }
# Binär-Start-Modus
  
header("Content-type: $content");
 }else{
# Binär-Download-Modus
  
header("Content-type: application/octet-stream");
  
header("Content-Disposition: attachment; filename=\"".basename($trail)."\"");
 }
 
header("Last-Modified: ".gmdate("D, d M Y H:i:s T",$filemtime));    // TODO: Alter der Zipdatei übermitteln
 
header("Content-Length: ".strlen($data));
 echo 
$data;
}else{
# Listing-Modus
// echo"<pre>";
// var_dump($file);

// Listing generieren: Dateinamen haben Pfade; (leere) Verzeichnisse können, müssen aber nicht gelistet sein
 
$ls=$ais_mode?list_ais($file):list_zip($file);
 if (!
$lsphpinfo(INFO_VARIABLES);
// Listing auf eine Verzeichnisebene (je nach $trail) herunterbrechen:
 
$dir=array();
 foreach (
$ls as $e) {
  if (
$trail) {
   if (
strpos($e['name'],$trail)!==0) continue;    // übergeordnet: Nicht listen!
   
$e['name']=substr($e['name'],strlen($trail));
   if (!
$e['name']) continue;        // Verzeichnis selbst: nicht listen!
  
}
  if (
$e['time']<=315619200$e['time']="k. A.";    // ≤ 2.1.1980 sei ungültig
  
else if ($filemtime<$e['time']) $filemtime=$e['time'];    // Maximumsuche
  
$i=strpos($e['name'],'/');
  if (
$i!==false) {        // Eine tiefer liegede Datei (oder Verzeichnis)?
   
$n=substr($e['name'],0,$i);    // Rest löschen
   
if (!$sumsize || !array_key_exists($n,$sumsize)) {
    
$e['name']=$n;        // kürzen
    
$e['dir']='/';        // Verzeichnis-Marker setzen
    
array_push($dir,$e);    // aufsammeln
   
}
   
$sumsize[$n]+=$e['size'];    // Gesamt-Größe der untergeordneten Dateien
  
}else array_push($dir,$e);    // normale Datei aufsammeln
 
}
 unset(
$ls);            // Listing wird nicht mehr benötigt
 
if (!count($dir)) {
  
Fehler($info."\n".$file);
 }
// Summengröße an DirEnts anhängen
 
if ($sumsize) foreach ($sumsize as $n => $size) {
  foreach (
$dir as &$e) {
   if (
$e['name']==$n) break;    // muss laut Programmlogik klappen!
  
}
  
$e['size']=$size;
 }
 unset(
$sumsize,$e);    // weg damit!
// Beschreibung anhängen
 
foreach ($dir as &$e) {
  
$e['desc']=Desc($e['name']);
 }
 unset(
$e);        // gefährliche Referenz löschen!
// echo"</pre>";
// var_dump($dir);

 
header("Content-type: text/html; charset=utf-8");
// Datum der neuesten Datei übermitteln,
// auch die (nicht gezeigten) in Unterverzeichnissen mitzählen,
// aber nicht die in übergeordneten Verzeichnissen.
 
if ($filemtimeheader("Last-Modified: ".gmdate("D, d M Y H:i:s T",$filemtime));
 
OutHtmlHeader(s("con").$info,null);
 echo 
"<BODY>\n";

 echo 
"<h1><small>".s("con");
 
OutUrl($info,$trail);
 echo 
"</small></h1>\n";

 echo 
"<TABLE class='sortable filelist'>\n";
 echo 
"<thead><tr>";
 echo 
"<th class=sorted>{$_['u']}";
 echo 
"<th>{$_['n']}";
 echo 
"<th>{$_['e']}";
 echo 
"<th>{$_['m']}";
 echo 
"<th>{$_['s']}";
 echo 
"<th>{$_['d']}";
 echo 
"</thead>\n";
 
 
$gr=0;                # Dateigröße
 
$nf=0;                # Anzahl Dateien
 
foreach($dir as $e) {
  
$g=guck($e['name']);
//  if ($g=="X" && $e['size']>4096) $g="P";    # Default: Pixeldump für große Dateien
  
printf("<tr><td%s>",
    ((
$mimetype && ($mimetype!="text/html")) ?
    
" title=\"".s("mt")."'".$mimetype."'!\"" ""));
  if (
$g) {
   if (
$g=="PS" || $g=="PSZ") {
    
printf("<A href=\"%s?bin=PDF%s\" title=\"%s\">PDF</A> ",
      
Esc($e['name']), preg_match("/\.GE.$/",$e['name'])?"R":""s("pk"));
   }
   
$cp=$DefaultCP;    // Vorher-Umkodierung (zu UTF-8)
   
if ($g=="TXW"$cp="oem";
   if (
$g=='P' || $g=='X'$cp="as";
   else if (
in_array($g,$binaries)) $cp="bin";
//   if ($mimetype) $cp="bin";
   
$verb=s("an");    // angucken (Bilder)
   
if ($mimetype && substr($mimetype,0,strpos($mimetype,'/'))=="audio"$verb=s("ah");    // anhören
   
else if ($mimetype && $mimetype!="text/html" && $mimetype!="application/postscript"$verb=s("st");    // starten
   
else if ($g=="X"$verb="<small>Hexdump";
   else if (
$g=="P"$verb="<small>Pixeldump";
   echo 
"<a href=\"".Esc($e['name'])."?$cp=$g$ForceLang\">$verb</a>";
  }else{
   echo 
" ";
  }
  
$size=$e['size'];
  echo 
"<td colspan=2 title=\"".s($e['dir']=='/'?"hw":"hl")."\">";
  echo 
"<A href=\"".Esc($e['name']).$e['dir']."\">".AnsiName($e['name'])."</A>".$e['dir'];
  echo 
"<td align=right sortkey={$e['time']}>".gmdate("Y-m-d H:i:s",$e['time']);
  
$pretty=grouped($size);
  if (
$e['dir']=='/'$pretty="(Σ $pretty)";
  
printf("<td title=\"%s, =%04Xh\" align=right sortkey=$size>$pretty",
    
s("ub"),$size);
  echo 
"<td>{$e['desc']}\n";
  if (
$e['dir']!='/') {
   
$gr+=$size;    # zählt nicht Verzeichnisse, die mit Σ beginnen
   
$nf++;
  }
 }
 
printf("<tfoot><tr><td> <td colspan=2>%d %s<td> <td align=right>".
   
"Σ %s<td> ",$nf,s("da"),grouped($gr));
 echo 
"</tfoot>\n</TABLE>\n";
 echo 
s("foot");
 echo 
"</BODY></HTML>\n";
}
?>