Seite 1 von 1

Dateidownload

Verfasst: Di 19. Mär 2013, 10:39
von p.hintermayer
Da ich für einen unseren Kunden ein kleinen Dateidownload für webEdition realisiert habe, teile ich mein Snippet mit anderen - vielleicht benötigt es ja der ein oder andere.

Funktion: Anhand der File ID holt er sich die entsprechenden Informationen aus der Datenbank, setzt die Header und "fordert" den Browser zum Dateidownload auf.
Es wird überprüft, ob es eine Datei und kein Ordner ist, die Datei veröffentlicht wurde und die Datei durchsuchbar ist (Hauptkriterium zur Beschränkung).

PHP Code:

Code: Alles auswählen

/**
 * check, if passed key is a valid integer
 */

$file_id = filter_var(key($_GET), FILTER_SANITIZE_NUMBER_INT);

if(empty($file_id) === false)
{
    /**
     * get file information from database
     * Crits: Searchable, no folder, published
     */
    
    $sql = '
    SELECT
        *
    FROM
        `tblFile`
    WHERE
        `ID` = ' . $db->real_escape_string($file_id) . '
    AND
        `IsSearchable` = 1
    AND
        `IsFolder` = 0
    AND
        `Published` != 0
    LIMIT 1;';
    
    $result = $db->query($sql);
    
    
    /**
     * check, if entry exists
     */
    
    if($result->num_rows === 1)
    {
        $data = $result->fetch_assoc();
        
        $file = $_SERVER['DOCUMENT_ROOT'] . $data['Path'];
        
        /**
         * check if file exists
         */
        
        if(is_file($file))
        {
            $contentType = $data['ContentType'];

            if(substr($contentType, -1) === '*')
            {
                $contentType = substr($contentType, 0, -1) . substr($data['Extension'], 1);
            }

            /**
             * output the file
             */
            
            header('Content-Type: ' . $contentType);
            header('Content-Transfer-Encoding: binary');
            header('Content-Length:' . filesize($file));
            header('Content-Disposition: attachment; filename=' . $data['Filename']);
            
            readfile($file);
        }
        else 
        {
            echo 'file not found.';
        }
    }
    else 
    {
        echo 'file not found.';
    }
}
Beispieleinsatz: <a href="/download.php?123" title="Download">Download</a>

Re: Dateidownload

Verfasst: Mi 20. Mär 2013, 11:24
von p.hintermayer
Da ich den 1. Beitrag nicht editieren kann, folgt das Update nun in diesem Post.

Änderungen zum 1. Post: webEdition Seiten sind ausgenommen, SQL basierend, file key implementiert

Code: Alles auswählen

/**
 * check, if passed key or value of index file is a valid integer
 * example: download.php?123 || download.php?file=123
 */

$file_id = filter_var(key($_GET), FILTER_VALIDATE_INT) !== false 
           ? key($_GET) 
           : filter_input(INPUT_GET, 'file', FILTER_SANITIZE_NUMBER_INT);

if(empty($file_id) === false)
{
    /**
     * get file information from database
     * Crits: Searchable, no folder, published, no webEdition page
     */
    
    $sql = '
    SELECT
        IF(RIGHT(`ContentType`, 1) = "*", CONCAT(SUBSTRING_INDEX(`ContentType`, "*", 1), SUBSTR(`Extension`, 2)), `ContentType`) AS `ContentType`,
        CONCAT("' . $_SERVER['DOCUMENT_ROOT'] . '", `Path`) AS `File`,
        `Filename`
    FROM
        `tblFile`
    WHERE
        `ID` = ' . $db->real_escape_string($file_id) . '
    AND
        `ContentType` != "text/webedition"
    AND
        `IsSearchable` = 1
    AND
        `IsFolder` = 0
    AND
        `Published` != 0
    LIMIT 1;';

    $result = $db->query($sql);
    
    
    /**
     * check, if entry exists
     */
    
    if($result->num_rows === 1)
    {
        $data = $result->fetch_assoc();

        /**
         * check, if file exists
         */
        
        if(is_file($data['File']))
        {
            header('Content-Description: File Transfer'); 
            header('Content-Type: ' . $data['ContentType']);
            header('Content-Transfer-Encoding: binary');
            header('Content-Length:' . filesize($data['File']));
            header('Content-Disposition: attachment; filename=' . $data['Filename']);
            
            readfile($data['File']);
        }
        else 
        {
            echo 'file not found.';
        }
    }
    else 
    {
        echo 'file not found.';
    }
}

Re: Dateidownload

Verfasst: Mi 20. Mär 2013, 21:58
von mokraemer
kleine Anmerkung:
wenn du $db->real_escape_string durch intval() ersetzt, sparst du dir die DB connection
In der Vorlage kannst du getHash('SELECT..',$GLOBALS['DB_WE']); nutzen, dann hast du auch gleich noch die WE Fehlerbehandlung etc. drin.

Re: Dateidownload

Verfasst: Do 21. Mär 2013, 11:20
von p.hintermayer
wenn du $db->real_escape_string durch intval() ersetzt, sparst du dir die DB connection
Nein, das wäre eine Sicherheitslücke, da dadurch Hex Injections möglich wären.

Re: Dateidownload

Verfasst: Do 21. Mär 2013, 16:41
von WBTMagnum
p.hintermayer hat geschrieben:Nein, das wäre eine Sicherheitslücke, da dadurch Hex Injections möglich wären.
Bist du dir da sicher? Dazu habe ich jetzt nichts gefunden. Auf stackoverflow sehen sie hier auch kein Problem: http://stackoverflow.com/questions/3208 ... base-input

LG,
Sascha

Re: Dateidownload

Verfasst: Do 21. Mär 2013, 20:03
von mokraemer
glaube ich auch nicht - und was bitte sollen "Hex Injections" sein?
Ich kann bei dir beliebige Zahlen übergeben - ob ich die nun als Hex-Wert oder Zahl übergebe ist dann egal. Für die Query steht dann da eine Zahl - sprich dort kommt das gleiche raus und du brichst nicht aus dem SQL aus.