moellit: Datei Download "ausserhalb" des Apache ?!

Hallo zusammen,

also, ich hab folgendes vor:

ich hab nen script, das nach *.mp3 dateien auf meiner festplatte, in einem festgelegten verzeichnis, sucht -> AUSSERHALB des Webserver z.B. in c:\mp3 und nicht in (absoluter pfad) c:\apache\htdocs
...das ist auch kein problem !
(das ganze läuft innerhalb eines lokalen netzwerkes)

wenn jetzt jemand auf die seite zugreift, erhählt er eine liste der dateien !

wie kann ich es nun realisieren, das er diese auch downloaden kann ?
bisher habe ich es folgendermassen versucht:
der link sieht so aus:

file://verzeichnis/datei.mp3

das geht allerdings nur lokal auf meinem rechner !

was muss ich machen um anderen benutzer die datei zur verfügung zu stellen ? hat das irgendwas mit zugriffsrechten zutun ?

danke schonmal
 moellit

  1. ich hab nen script, das nach *.mp3 dateien auf meiner festplatte, in einem festgelegten verzeichnis, sucht -> AUSSERHALB des Webserver z.B. in c:\mp3 und nicht in (absoluter pfad) c:\apache\htdocs

    wenn jetzt jemand auf die seite zugreift, erhählt er eine liste der dateien !

    wie kann ich es nun realisieren, das er diese auch downloaden kann ?

    Dann solltest Du in diese Liste Verweise auf die Dateien einbauen, beispielhafterweise so:

    while ($dateiname=verzeichniseintrag_lesen())
       {
        echo "<li><a href="".htmlentities($dateiname)."">".htmlentities($dateiname)."</a></li>\n";
       };

    Gruß,
      soenk.e

    1. Hallo,

      while ($dateiname=verzeichniseintrag_lesen())
         {
          echo "<li><a href="".htmlentities($dateiname)."">".htmlentities($dateiname)."</a></li>\n";
         };

      Das wird dann beim Klick auf die Links Zugriffsyfehler geben. Was Du brauchst ist ein Script, dass die angeforderte Datei ausliefert. Links müssen also das Script refenzieren und den Namen der angeforderten Datei irgendwie als Get-Varíable übergeben. Den Pfad würde ich dann Scriptseitig dazuaddieren.

      Mit readfile($pfad.$dateiname) kannst Du Die Dateien dann ausgeben. Allerdings sollte vor dem Readfile immer noch der Doctype per header() - Funktion ausgegeben werden.

      Der Apache hat für HTTP keinen Zugriff auf die Dateien außerhalb der Dokument-Root, der wwwrun (PHP) schon, wenn er als User darauf zugreifen darf (Gruppeneinstellung oder chown).

      Liebe Grüße aus http://www.braunschweig.de

      Tom

      1. In Ergänzung meines Vorredners...

        Du hast sicher Windows NT, XP, oder 2000. Der Apache startet standardgemäß als Dienst mit der Systemkennung, hat also mehr Rechte als der Administrator. Wenn Du das nicht verändert hast (Systemsteuerung oder MMC-> Dienste) dann hat der Indianer also Zugriffe und es geht wie vom Vorredner beschrieben.

        (Ich persönlich würde das aber nicht so lassen- es ist unter Umständen ein Sicherheitsloch. Ich hab dem Apache einen extra Benutzer gebaut und entsprechend beschränkt)

        Startest Du den Apache aber von Hand als PROGRAMM oder über einen Autostart - Eintrag (Registry oder Gruppe) dann hat er die Rechte, die Du auch hast.

        fastix

        1. hallo nochmal,

          also es funktioniert, wenn ich die zeile:

          include "include/__header.inc";

          im script weglasse !
          problem: da stehen auch informationen drin die ich bräuchte, also wie kann ich mehrere header einbinden, oder einen existierenden header überschreiben/löschen ?

          moellit

          1. hallo nochmal,

            also es funktioniert, wenn ich die zeile:

            include "include/__header.inc";

            im script weglasse !
            problem: da stehen auch informationen drin die ich bräuchte, also wie kann ich mehrere header einbinden, oder einen existierenden header überschreiben/löschen ?

            moellit

            KLAPPT  ;-)

            ich hab einfach nen trick benutzt..

            include "include/__header.inc";

            diese zeile ans ende des scriptes geschrieben, OK das ist vielleicht nicht gerade besonders elegant, aber hauptsache es funktioniert

            moellit

            1. Hi,

              ich hab einfach nen trick benutzt..

              include "include/__header.inc";

              diese zeile ans ende des scriptes geschrieben, OK das ist vielleicht nicht gerade besonders elegant, aber hauptsache es funktioniert

              Das könnte eventuell also unter ganz dummen Umständen und nur wirklich vielleicht auch daran liegen, dass Deine Include-Datei Ausgaben produziert. Das passiert immer dann, wenn die Include-Datei mit vor dem <?php oder nach dem ?> noch irgendwelche Zeichen, Leerzeilen enthält. Ein CRLF oder LF reichen schon. Leider sind die in den meisten Texteditoren unsichtbar.

              Liebe Grüße aus http://www.braunschweig.de

              Tom

              1. das ist alles was in der datei __header.inc steht !
                ..sollte doch eigentlich gehen ?!

                <html>
                 <head>
                 <link rel=stylesheet type="text/css" href="format.css">
                 <title>Moeller´s Site</title>
                 </head>
                 <body>

                moellit

                1. Hi,

                  das ist alles was in der datei __header.inc steht !
                  ..sollte doch eigentlich gehen ?!

                  <html>
                   <head>
                   <link rel=stylesheet type="text/css" href="format.css">
                   <title>Moeller´s Site</title>
                   </head>
                   <body>

                  Das ist ja schlimmer, als ich gedacht habe. Wenn Du diese Zeilen innerhalb Deines PHP-Codes includest, dann weiß ich gar nicht, was da wirklich passiert. Stell Dir vor, das würde genau an die Stelle geschrieben, wo die include-Funktion aufgerufen wird. Dann führt es ja bestimmt zu Ausgaben auf dem Browser. Ich würde das anders machen:

                  function get_cont($dateiname)
                  {
                    $fp = @fopen($dateiname);
                    if ($fp)
                    {
                      $dateiinhalt=fread($fp,filesize($dateiname));
                      fclose($fp);
                    }
                    else
                    {
                      $dateiinhalt=false;
                    }
                    return $dateiinhalt;
                  }

                  Die Funktion nimmst Du in dein Standardrepertoire auf und rufst sie auf, wann immer Du willst. Genau dann, wenn es passieren soll (natürlich nach dem Funktionsaufruf und allen header()-Aufrufen), gibst Du die Variable $dateiinhalt einfach mit einem simplen
                  echo $dateiinhalt; aus.

                  Dann passiert der Fehler nicht mehr.

                  Liebe Grüße aus http://www.braunschweig.de

                  Tom

      2. hallo,

        ok, ich hab das jetzt folgendermassen versucht:

        function download($verzeichnis,$datei)
         {
          header("Content-type: application/x-msdownload",FALSE);
          header("Content-Disposition: attachment; filename=$datei");
          $pfad = $verzeichnis . $datei;
          readfile($pfad);
         }

        problem: folgende fehler:
        Warning: Cannot add header information - headers already sent by (output started at c:\programme\apache\apache\htdocs\moeller\include\__header.inc:5) in c:\programme\apache\apache\htdocs\moeller\login.php on line 278

        -> weie kann ich den existierenden header überschreiben/löschen
        hab das oben schon mit der angabe FALSE versucht, geht aber nicht !

        und fehler nr.2

        er gibt mir den dateiinhalt im browser aus ! -> also KEIN download sondern auslesen und anzeigen der datei !

        noch zur info
        ich hab windoof 2000 + IE 5 !

        moellit

      3. Hallo,

        while ($dateiname=verzeichniseintrag_lesen()) {
            echo "<li><a href="".htmlentities($dateiname)."">".htmlentities($dateiname)."</a></li>\n";
          };

        Das wird dann beim Klick auf die Links Zugriffsyfehler geben. Was Du brauchst ist ein Script, dass die angeforderte Datei ausliefert. Links müssen also das Script refenzieren und den Namen der angeforderten Datei irgendwie als Get-Varíable übergeben. Den Pfad würde ich dann Scriptseitig dazuaddieren.

        Mit readfile($pfad.$dateiname) kannst Du Die Dateien dann ausgeben. [...]

        Mökmök! Ich weis ja nicht, wie readfile() mit Pipes ala $dateiname = "datei | rm -r /*"; umgeht, aber ohne absolut wasserdichte Überprüfung der Usereingaben würde ich keine Variablen auf mein System loslassen. :)

        Imho sollte folgendes Konzept einigermaßen tauglich sein (Variableninitialisierung und Fehlerbehandlung dazudenken ;-):

        $dir = "/path/to/mp3s";
        $dh  = opendir($dir);
        $filepath = $file = '';
        while ($file = readdir($dh)) {
                $filepath = "$dir/$file";
           clearstatchache();
         if (is_file($filepath)) $files[$file] = $filepath;
        }
        closedir($dh);
        .
        .
        .
        if (isset($files[$_REQUEST['file']]) &&
            $filepath = $files[$_REQUEST['file']]) {
         // Hier Dateisachen mit ungefährlichem $filepath machen
        }

        Das ist imho besser gegen unerwünschte Eingaben, als die Eingabe selbst zu "entschärfen", weil nur gültige Eingaben zum Erfolg führen und ungültige verworfen werden.

        Gruß Alex

        1. Hi Alex,

          Mökmök! Ich weis ja nicht, wie readfile() mit Pipes ala $dateiname = "datei | rm -r /*"; umgeht, aber ohne absolut wasserdichte Überprüfung der Usereingaben würde ich keine Variablen auf mein System loslassen. :)

          Senf, Ketchup...

          Gute Frage von Dir. Hast Du's denn schon mal ausprobiert, ob readfile auch Parameter übernimmt? Ich würde, an der Stelle von readfile() nur arbeiten, wenn argc == 2 ist. Das Pipe-Symbol wird allerdings schon von der Shell erkannt und deshalb werde ich das doch mal ausprobieren. Muss ja nicht gleich rm * -R sein für den Anfang.

          Liebe Grüße aus http://www.braunschweig.de

          Tom

      4. while ($dateiname=verzeichniseintrag_lesen())
           {
            echo "<li><a href="".htmlentities($dateiname)."">".htmlentities($dateiname)."</a></li>\n";
           };

        Das wird dann beim Klick auf die Links Zugriffsyfehler geben.

        Ich bin davon ausgegangen, daß er das entsprechende Verzeichnis in den Verzeichnisbaum des Webservers eingebunden hat. Nur das es außerhalb des Haupt-DocumentRoot liegt, bedeutet ja noch nicht, daß man das Verzeichnis per http nicht einsehen kann.

        Gruß,
          soenk.e