|
<?php |
|
function errorout($code, $message) { |
|
// Makes dpkg know it's not a package |
|
header("Content-Type: text/plain"); |
|
|
|
// Generate the HTTP error header |
|
header($_SERVER["SERVER_PROTOCOL"] . " $code $message"); |
|
|
|
// Then print out the error. |
|
// Because the content type is plain text, escaping is not necessary. |
|
die($message); |
|
} |
|
|
|
$db = new mysqli("localhost", "myrepo", "mypassword"); // change parameters to what you use |
|
|
|
if ($db->connect_error) { |
|
errorout(500, "Couldn't connect to the database. Please try your download later."); |
|
} |
|
|
|
$db->set_charset("utf8") |
|
or errorout(500, "Couldn't set up the database. Please try your download later."); |
|
|
|
$db->select_db($link, "myrepodb") // change myrepodb to your database name |
|
or errorout(500, "Couldn't open the database. Please try your download later."); |
|
|
|
// Exit here if the filename hasn’t been provided. |
|
if (!isset($_GET["filename"]) or empty($_GET["filename"])) { |
|
errorout(404, "The file you requested either doesn't exist or isn't allowed to be downloaded."); |
|
} |
|
|
|
// Store the filename in a variable, escaping it to be safe. |
|
$file = $db->real_escape_string($_GET["filename"]); |
|
|
|
// Determine the file path. |
|
// Packages and Release are expected to be in the same folder as this script. |
|
// Anything else is expected to be in a downloads/ folder. |
|
if ($file == "Packages" or strpos($file, "Packages.") === 0 |
|
or $file == "Release" or strpos($file, "Release.") === 0) { |
|
$path = $file; |
|
} else { |
|
$path = "downloads/$file"; |
|
} |
|
|
|
// The following code checks for attempts to read files that aren't debs. |
|
// Not doing this lets attackers read PHP scripts and system files. |
|
if (stristr($file, "..") or stristr($file, "/") or stristr($file, "\\") or !file_exists($file)) { |
|
errorout(404, "The file you requested either doesn't exist or isn't allowed to be downloaded."); |
|
} |
|
|
|
// Count the download in the database |
|
// A log will be saved if something goes wrong. |
|
try { |
|
// Check whether the package has already been downloaded. |
|
// We select an empty string as we don’t read the result, we just want to know if the row exists. |
|
$query = $db->query("SELECT '' FROM downloads WHERE filename='$file'"); |
|
|
|
if (!$query or $query->num_rows == 0) { |
|
// If it doesn't exist, create the row |
|
$db->query("INSERT INTO downloads SET filename='$file', count=1, first_download=NOW(), last_download=NOW()"); |
|
} else { |
|
// If it does, add one to the counter |
|
$db->query("UPDATE downloads SET count=count+1, last_download=NOW() WHERE filename='$file'"); |
|
} |
|
} catch (Exception $e) { |
|
// Something went wrong, so save a log file and continue onto the download |
|
// (The document root is usually htdocs or public_html) |
|
file_put_contents(dirname($_SERVER["DOCUMENT_ROOT"]) . "/../cydiaerr.log", print_r($e, true)); |
|
} |
|
|
|
// Finally, serve the user the file they requested |
|
$filesize = filesize($path); |
|
|
|
// If it's more than 16 bytes long, it's ok to serve it |
|
if ($filesize > 16) { |
|
// Force browsers to download the file, not display it |
|
header("Content-Type: application/octet-stream"); |
|
header("Content-Disposition: attachment; filename=\"$file\""); |
|
|
|
// Indicate how big the file is |
|
header("Content-Length: " . $filesize); |
|
|
|
// And finally, output the file! |
|
// It’s important to use readfile() as this buffers the output (reads and outputs small amounts at a time). |
|
// Reading the entire file into a string with file_get_contents() will use huge amounts of memory for bigger files. |
|
readfile($path); |
|
} else { |
|
errorout(404, "The file you requested either doesn't exist or isn't allowed to be downloaded."); |
|
} |
What do we need to add to our depiction file?