Beispiel #1
0
 public function testBuildStringFromArray()
 {
     $array = array(1, 2, 42);
     $this->assertEquals('1+2+42', \Elabftw\Elabftw\Tools::buildStringFromArray($array));
     $this->assertEquals('1-2-42', \Elabftw\Elabftw\Tools::buildStringFromArray($array, '-'));
     $this->assertFalse(\Elabftw\Elabftw\Tools::buildStringFromArray('pwet'));
 }
Beispiel #2
0
 /**
  * Called from ImportZip class
  *
  * @param string $file The string of the local file path stored in .elabftw.json of the zip archive
  */
 public function uploadLocalFile($file)
 {
     if (!is_readable($file)) {
         throw new Exception('No file here!');
     }
     $realName = basename($file);
     $longName = $this->getCleanName() . "." . Tools::getExt($realName);
     $fullPath = ELAB_ROOT . 'uploads/' . $longName;
     $this->moveFile($file, $fullPath);
     $this->dbInsert($realName, $longName, $this->getHash($fullPath));
 }
Beispiel #3
0
/**
 * Display a DB item (in mode=show).
 *
 * @param int $id The ID of the item to show
 * @param string $display Can be 'compact' or 'default'
 * @return string|null HTML of the single item
 */
function showDB($id, $display = 'default')
{
    global $pdo;
    $sql = "SELECT items.*,\n        items_types.bgcolor,\n        items_types.name\n        FROM items\n        LEFT JOIN items_types ON (items.type = items_types.id)\n        WHERE items.id = :id";
    $req = $pdo->prepare($sql);
    $req->execute(array('id' => $id));
    $item = $req->fetch();
    if ($display === 'compact') {
        // COMPACT MODE //
        ?>
            <section class='item_compact' style='border-left: 6px solid #<?php 
        echo $item['bgcolor'];
        ?>
'>
            <a href='database.php?mode=view&id=<?php 
        echo $item['id'];
        ?>
'>
            <span class='date date_compact'><?php 
        echo $item['date'];
        ?>
</span>
            <h4 style='padding-left:10px;border-right:1px dotted #ccd;color:#<?php 
        echo $item['bgcolor'];
        ?>
'><?php 
        echo $item['name'];
        ?>
 </h4>
            <span style='margin-left:7px'><?php 
        echo stripslashes($item['title']);
        ?>
</span>
        <?php 
        // STAR RATING read only
        show_stars($item['rating']);
        echo "</a></section>";
    } else {
        // NOT COMPACT
        echo "<section class='item' style='border-left: 6px solid #" . $item['bgcolor'] . "'>";
        echo "<a href='database.php?mode=view&id=" . $item['id'] . "'>";
        // show attached if there is a file attached
        if (has_attachement($item['id'], 'items')) {
            echo "<img style='clear:both' class='align_right' src='img/attached.png' alt='file attached' />";
        }
        // STARS
        show_stars($item['rating']);
        echo "<p class='title'>";
        // show lock if item is locked on viewDB
        if ($item['locked'] == 1) {
            echo "<img style='padding-bottom:3px;' src='img/lock-blue.png' alt='lock' />";
        }
        // TITLE
        echo stripslashes($item['title']) . "</p></a>";
        // ITEM TYPE
        echo "<span style='text-transform:uppercase;font-size:80%;padding-left:20px;color:#" . $item['bgcolor'] . "'>" . $item['name'] . " </span>";
        // DATE
        echo "<span class='date' style='padding:0 5px;'><img class='image' src='img/calendar.png' /> " . Tools::formatDate($item['date']) . "</span> ";
        // TAGS
        echo show_tags($id, 'items_tags');
        echo "</section>";
    }
}
Beispiel #4
0
                <p class='inline'><?php 
            echo _('Export this result:');
            ?>
 </p>
                <a href='make.php?what=zip&id=<?php 
            echo Tools::buildStringFromArray($results_arr);
            ?>
&type=<?php 
            echo $search_type;
            ?>
'>
                    <img src='img/zip.png' title='make a zip archive' alt='zip' />
                </a>

                <a href='make.php?what=csv&id=<?php 
            echo Tools::buildStringFromArray($results_arr);
            ?>
&type=<?php 
            echo $search_type;
            ?>
'>
                    <img src='img/spreadsheet.png' title='Export in spreadsheet file' alt='Export CSV' />
                </a>
            </div>
            <?php 
            echo "<p class='smallgray'>" . count($results_arr) . " " . ngettext("result found", "results found", count($results_arr)) . " (" . $total_time['time'] . " " . $total_time['unit'] . ")</p>";
            // Display results
            echo "<hr>";
            foreach ($results_arr as $id) {
                if ($search_type === 'experiments') {
                    showXP($id, $_SESSION['prefs']['display']);
Beispiel #5
0
            // not an image
        } elseif (in_array($ext, $common_extensions)) {
            echo "<img class='thumb' src='img/thumb-" . $ext . ".png' alt='' />";
            // special case for mol files
        } elseif ($ext === 'mol' && $_SESSION['prefs']['chem_editor'] && $_GET['mode'] === 'view') {
            // we need to escape \n in the mol file or we get unterminated string literal error in JS
            $mol = str_replace("\n", "\\n", file_get_contents(ELAB_ROOT . 'uploads/' . $uploads_data['long_name']));
            echo "<div class='center'><script>\n                  showMol('" . $mol . "');\n                  </script></div>";
        } else {
            // uncommon extension without a nice image to display
            echo "<img class='thumb' src='img/thumb.png' alt='' />";
        }
        // now display the name + comment with icons
        echo "<div class='caption'><img src='img/attached.png' class='bot5px' alt='attached' /> ";
        echo "<a href='app/download.php?f=" . $uploads_data['long_name'] . "&name=" . $uploads_data['real_name'] . "' target='_blank'>" . $uploads_data['real_name'] . "</a>";
        echo "<span class='smallgray' style='display:inline'> " . Tools::formatBytes(filesize('uploads/' . $uploads_data['long_name'])) . "</span><br>";
        // if we are in view mode, we don't show the comment if it's the default text
        // this is to avoid showing 'Click to add a comment' where in fact you can't click to add a comment because
        // your are in view mode
        $comment = "<img src='img/comment.png' class='bot5px' alt='comment' />\n                    <p class='editable inline' id='filecomment_" . $uploads_data['id'] . "'>" . stripslashes($uploads_data['comment']) . "</p>";
        if ($_GET['mode'] === 'edit' || $uploads_data['comment'] != 'Click to add a comment') {
            echo $comment;
        }
        echo "</div></div></div>";
    }
    // end while
    echo "</div></div>";
}
// end if there is at least one file uploaded
// END DISPLAY FILES
echo "</div>";
Beispiel #6
0
    $users_count = $req->rowCount();
    // redirect to register page if no users are in the database
    if ($users_count === 0) {
        header('Location: ../register.php');
    } else {
        $message = 'It looks like eLabFTW is already installed. Delete the config file if you wish to reinstall it.';
        display_message('error_nocross', $message);
        custom_die();
    }
}
?>

<h3>Preliminary checks</h3>
<?php 
// CHECK WE ARE WITH HTTPS
if (!\Elabftw\Elabftw\Tools::usingSsl()) {
    // get the url to display a link to click (without the port)
    $url = 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
    $message = "eLabFTW works only in HTTPS. Please enable HTTPS on your server. Or click this link : <a href='{$url}'>{$url}</a>";
    display_message('error_nocross', $message);
    custom_die();
}
// CHECK PHP version
if (!function_exists('version_compare') || version_compare(PHP_VERSION, '5.5', '<')) {
    $message = "Your version of PHP isn't recent enough. Please update your php version to at least 5.5";
    display_message('error_nocross', $message);
    $errflag = true;
}
// Check for hash function
if (!function_exists('hash')) {
    $message = "You don't have the hash function. On Freebsd it's in /usr/ports/security/php5-hash.";
Beispiel #7
0
 * Login page
 *
 */
use Elabftw\Elabftw\Tools;
require_once 'inc/common.php';
$page_title = _('Login');
$selected_menu = null;
// Check if already logged in
if (isset($_SESSION['auth']) && $_SESSION['auth'] === 1) {
    header('Location: experiments.php');
    exit;
}
require_once 'inc/head.php';
$formKey = new \Elabftw\Elabftw\FormKey();
// if we are not in https, die saying we work only in https
if (!Tools::usingSsl()) {
    // get the url to display a link to click (without the port)
    $url = 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['PHP_SELF'];
    $message = "eLabFTW works only in HTTPS. Please enable HTTPS on your server. Or click this link : <a href='{$url}'>{$url}</a>";
    display_message('error', $message);
    require_once 'inc/footer.php';
    exit;
}
// Check if we are banned after too much failed login attempts
$sql = "SELECT user_infos FROM banned_users WHERE time > :ban_time";
$req = $pdo->prepare($sql);
$req->execute(array(':ban_time' => date("Y-m-d H:i:s", strtotime('-' . get_config('ban_time') . ' minutes'))));
$banned_users_arr = array();
while ($banned_users = $req->fetch()) {
    $banned_users_arr[] = $banned_users['user_infos'];
}
Beispiel #8
0
    $sql = "SELECT userid, real_name, long_name, item_id FROM uploads WHERE id = :id";
    $req = $pdo->prepare($sql);
    $req->bindParam(':id', $id, PDO::PARAM_INT);
    $req->execute();
    $data = $req->fetch();
    if ($data['userid'] == $_SESSION['userid']) {
        // Good to go -> delete file from SQL table
        $sql = "DELETE FROM uploads WHERE id = :id";
        $reqdel = $pdo->prepare($sql);
        $reqdel->bindParam(':id', $id, PDO::PARAM_INT);
        $reqdel->execute();
        // now delete it from filesystem
        $filepath = ELAB_ROOT . 'uploads/' . $data['long_name'];
        unlink($filepath);
        // remove thumbnail
        $ext = Tools::getExt($data['real_name']);
        if (file_exists(ELAB_ROOT . 'uploads/' . $data['long_name'] . '_th.' . $ext)) {
            unlink(ELAB_ROOT . 'uploads/' . $data['long_name'] . '_th.' . $ext);
        }
        // Redirect to the viewXP
        $msg_arr = array();
        $msg_arr[] = sprintf(_('File %s deleted successfully.'), $data['real_name']);
        $_SESSION['infos'] = $msg_arr;
        header("location: ../experiments.php?mode=edit&id=" . $data['item_id']);
    } else {
        die;
    }
    // DATABASE ITEM
} elseif ($_GET['type'] === 'items') {
    // Get realname
    $sql = "SELECT real_name, long_name, item_id FROM uploads WHERE id = :id AND type = 'items'";
Beispiel #9
0
$req->bindParam(':id', $id, PDO::PARAM_INT);
$req->execute();
// got results ?
$row_count = $req->rowCount();
if ($row_count === 0) {
    display_message('error', _('Nothing to show with this ID.'));
    require_once 'inc/footer.php';
    exit;
}
$data = $req->fetch();
?>
<!-- begin item view -->
<section class="box">

<span class='date_view'><img src='img/calendar.png' title='date' alt='Date :' /> <?php 
echo Tools::formatDate($data['date']);
?>
</span><br>
<?php 
show_stars($data['rating']);
// buttons
echo "<a href='database.php?mode=edit&id=" . $data['itemid'] . "'><img src='img/pen-blue.png' title='edit' alt='edit' /></a> \n<a href='app/duplicate_item.php?id=" . $data['itemid'] . "&type=db'><img src='img/duplicate.png' title='duplicate item' alt='duplicate' /></a> \n<a href='make.php?what=pdf&id=" . $data['itemid'] . "&type=items'><img src='img/pdf.png' title='make a pdf' alt='pdf' /></a> \n<a href='make.php?what=zip&id=" . $data['itemid'] . "&type=items'><img src='img/zip.png' title='make a zip archive' alt='zip' /></a>\n<a href='experiments.php?mode=show&related=" . $data['itemid'] . "'><img src='img/link.png' alt='Linked experiments' title='Linked experiments' /></a> ";
// lock
if ($data['locked'] == 0) {
    echo "<a href='app/lock.php?id=" . $data['itemid'] . "&action=lock&type=items'><img src='img/unlock.png' title='lock item' alt='lock' /></a>";
} else {
    // item is locked
    echo "<a href='app/lock.php?id=" . $data['itemid'] . "&action=unlock&type=items'><img src='img/lock-gray.png' title='unlock item' alt='unlock' /></a>";
}
// TAGS
show_tags($id, 'items_tags');
Beispiel #10
0
 /**
  * If files are attached we want them!
  *
  * @throws Exception if it cannot rename the file or SQL request failed
  * @param string $file The path of the file in the archive
  */
 private function importFile($file)
 {
     // first move the file to the uploads folder
     $longName = hash("sha512", uniqid(rand(), true)) . '.' . \Elabftw\Elabftw\Tools::getExt($file);
     $newPath = ELAB_ROOT . 'uploads/' . $longName;
     if (!rename($this->tmpPath . '/' . $file, $newPath)) {
         throw new Exception('Cannot rename file!');
     }
     // make md5sum
     $md5 = hash_file('md5', $newPath);
     // now insert it in sql
     $sql = "INSERT INTO uploads(\n            real_name,\n            long_name,\n            comment,\n            item_id,\n            userid,\n            type,\n            md5\n        ) VALUES(\n            :real_name,\n            :long_name,\n            :comment,\n            :item_id,\n            :userid,\n            :type,\n            :md5\n        )";
     $req = $this->pdo->prepare($sql);
     $req->bindParam(':real_name', basename($file));
     $req->bindParam(':long_name', $longName);
     $req->bindValue(':comment', 'Click to add a comment');
     $req->bindParam(':item_id', $this->newItemId);
     $req->bindParam(':userid', $_SESSION['userid']);
     $req->bindValue(':type', $this->category);
     $req->bindParam(':md5', $md5);
     if (!$req->execute()) {
         throw new Exception('Cannot import in database!');
     }
 }
Beispiel #11
0
 /**
  * Build HTML content that will be fed to mpdf->WriteHTML()
  */
 private function buildContent()
 {
     $this->addCss();
     $this->content .= "<h1 style='margin-bottom:5px'>" . stripslashes($this->data['title']) . "</h1>\n            Date : " . Tools::formatDate($this->data['date']) . "<br />\n            Tags : <em>" . $this->tags . "</em><br />\n            Made by : " . $this->author . "\n            <hr>" . stripslashes($this->body);
     $this->addLinkedItems();
     $this->addAttachedFiles();
     $this->addComments();
     $this->addElabid();
     $this->addLockinfo();
     $this->addUrl();
     $this->content .= "<footer>PDF generated with <a href='http://www.elabftw.net'>elabftw</a>, a free and open source lab notebook</footer>";
 }
Beispiel #12
0
if ($type === 'experiments') {
    // we check that the user owns the experiment before adding things to it
    if (!is_owned_by_user($item_id, 'experiments', $_SESSION['userid'])) {
        die('Not your experiment');
    }
}
// check we actually have files
if (count($_FILES) === 0) {
    die('No files received');
}
// UPLOAD A FILE TO AN EXPERIMENT OR DB ITEM
if ($type === 'experiments' || $type == 'items') {
    // Create a clean filename : remplace all non letters/numbers by '.' (this way we don't lose the file extension)
    $realname = preg_replace('/[^A-Za-z0-9]/', '.', $_FILES['file']['name']);
    // get extension
    $ext = \Elabftw\Elabftw\Tools::getExt($realname);
    // Create a unique long filename + extension
    $longname = hash("sha512", uniqid(rand(), true)) . "." . $ext;
    // Try to move the file to its final place
    if (rename($_FILES['file']['tmp_name'], ELAB_ROOT . 'uploads/' . $longname)) {
        // generate a md5sum of the file if it's not too big
        if ($_FILES['file']['size'] < 5000000) {
            $md5 = hash_file('md5', ELAB_ROOT . 'uploads/' . $longname);
        } else {
            $md5 = null;
        }
        // SQL TO PUT FILE IN UPLOADS TABLE
        $sql = "INSERT INTO uploads(\n            real_name,\n            long_name,\n            comment,\n            item_id,\n            userid,\n            type,\n            md5\n        ) VALUES(\n            :real_name,\n            :long_name,\n            :comment,\n            :item_id,\n            :userid,\n            :type,\n            :md5\n        )";
        $req = $pdo->prepare($sql);
        $req->execute(array('real_name' => $realname, 'long_name' => $longname, 'comment' => 'Click to add a comment', 'item_id' => $item_id, 'userid' => $_SESSION['userid'], 'type' => $type, 'md5' => $md5));
    } else {
Beispiel #13
0
 /**
  * Reference the attached files (if any) in the pdf
  * Add also the hash sum
  */
 private function addAttachedFiles()
 {
     // SQL to get attached files
     $sql = "SELECT * FROM uploads WHERE item_id = :id AND type = :type";
     $req = $this->pdo->prepare($sql);
     $req->bindParam(':id', $this->id);
     $req->bindParam(':type', $this->type);
     $req->execute();
     $real_name = array();
     $long_name = array();
     $comment = array();
     $hash = array();
     $hash_algorithm = array();
     while ($uploads = $req->fetch()) {
         $real_name[] = $uploads['real_name'];
         $long_name[] = $uploads['long_name'];
         $comment[] = $uploads['comment'];
         $hash[] = $uploads['hash'];
         $hash_algorithm[] = $uploads['hash_algorithm'];
     }
     // do we have files attached ?
     if ($req->rowCount() > 0) {
         $this->content .= "<section class='no_break'>";
         if ($req->rowCount() === 1) {
             $this->content .= "<h3>Attached file :</h3>";
         } else {
             $this->content .= "<h3>Attached files :</h3>";
         }
         $this->content .= "<ul>";
         $real_name_cnt = $req->rowCount();
         for ($i = 0; $i < $real_name_cnt; $i++) {
             $this->content .= "<li>" . $real_name[$i];
             // add a comment ? don't add if it's the default text
             if ($comment[$i] != 'Click to add a comment') {
                 $this->content .= " (" . stripslashes(htmlspecialchars_decode($comment[$i])) . ")";
             }
             // add hash ? don't add if we don't have it
             // length must be greater (sha2 hashes) or equal (md5) 32 bits
             if (strlen($hash[$i]) >= 32) {
                 // we have hash
                 $this->content .= "<br>" . $hash_algorithm[$i] . " : " . $hash[$i];
             }
             // if this is an image file, add the thumbnail picture
             $ext = filter_var(Tools::getExt($real_name[$i]), FILTER_SANITIZE_STRING);
             $filepath = 'uploads/' . $long_name[$i];
             if (file_exists($filepath) && preg_match('/(jpg|jpeg|png|gif)$/i', $ext)) {
                 $this->content .= "<br /><img class='attached_image' src='" . $filepath . "' alt='attached image' />";
             }
             $this->content .= "</li>";
         }
         $this->content .= "</ul></section>";
     }
 }
Beispiel #14
0
    type = 'database';
}
var item_id = '<?php 
echo $id;
?>
';

// config for dropzone, id is camelCased.
Dropzone.options.elabftwDropzone = {
    // i18n message to user
    dictDefaultMessage: '<?php 
echo _('Drop files here to upload');
?>
',
    maxFilesize: '<?php 
echo Tools::returnMaxUploadSize();
?>
', // MB
    init: function() {
        this.on("complete", function() {
            // reload the #filesdiv once the file is uploaded
            if (this.getUploadingFiles().length === 0 && this.getQueuedFiles().length === 0) {
                $("#filesdiv").load(type + '.php?mode=edit&id=' + item_id + ' #filesdiv', function() {
                    // make the comment zone editable (fix issue #54)
                    $('.thumbnail p.editable').editable('app/editinplace.php', {
                     indicator : 'Saving...',
                     id   : 'id',
                     name : 'filecomment',
                     submit : 'Save',
                     cancel : 'Cancel',
                     style : 'display:inline'
Beispiel #15
0
 $sql = "DELETE FROM items WHERE id = :id";
 $req = $pdo->prepare($sql);
 $result[] = $req->execute(array('id' => $id));
 // delete associated tags
 $sql = "DELETE FROM items_tags WHERE item_id = :id";
 $req = $pdo->prepare($sql);
 $result[] = $req->execute(array('id' => $id));
 // delete associated files
 $sql = "SELECT real_name, long_name FROM uploads WHERE item_id = :id AND type = :type";
 $req = $pdo->prepare($sql);
 $req->execute(array('id' => $id, 'type' => 'items'));
 while ($uploads = $req->fetch()) {
     $filepath = ELAB_ROOT . 'uploads/' . $uploads['long_name'];
     unlink($filepath);
     // remove thumbnail
     $ext = Tools::getExt($uploads['real_name']);
     if (file_exists(ELAB_ROOT . 'uploads/' . $uploads['long_name'] . '_th.' . $ext)) {
         unlink(ELAB_ROOT . 'uploads/' . $uploads['long_name'] . '_th.' . $ext);
     }
 }
 // now remove them from the database
 $sql = "DELETE FROM uploads WHERE item_id = :id AND type = :type";
 $req = $pdo->prepare($sql);
 $result[] = $req->execute(array('id' => $id, 'type' => 'items'));
 // delete links of this item in experiments with this item linked
 // get all experiments with that item linked
 $sql = "SELECT id FROM experiments_links WHERE link_id = :link_id";
 $req = $pdo->prepare($sql);
 $result[] = $req->execute(array('link_id' => $id));
 while ($links = $req->fetch()) {
     $delete_sql = "DELETE FROM experiments_links WHERE id = :links_id";
Beispiel #16
0
}
// Display experiment
?>
    <section class="item" style='padding:15px;border-left: 6px solid #<?php 
echo $data['color'];
?>
'>
    <span class='top_right_status'><img src='img/status.png'><?php 
echo $data['name'];
?>
<img src='img/eye.png' alt='eye' /><?php 
echo $visibility;
?>
</span>
<?php 
echo "<span class='date_view'><img src='img/calendar.png' class='bot5px' title='date' alt='Date :' /> " . Tools::formatDate($data['date']) . "</span><br />\n    <a href='experiments.php?mode=edit&id=" . $data['expid'] . "'><img src='img/pen-blue.png' title='edit' alt='edit' /></a>\n<a href='app/duplicate_item.php?id=" . $data['expid'] . "&type=exp'><img src='img/duplicate.png' title='duplicate experiment' alt='duplicate' /></a>\n<a href='make.php?what=pdf&id=" . $data['expid'] . "&type=experiments'><img src='img/pdf.png' title='make a pdf' alt='pdf' /></a>\n<a href='make.php?what=zip&id=" . $data['expid'] . "&type=experiments'><img src='img/zip.png' title='make a zip archive' alt='zip' /></a> ";
// lock
if ($data['locked'] == 0) {
    echo "<a href='app/lock.php?id=" . $data['expid'] . "&action=lock&type=experiments'><img src='img/unlock.png' title='lock experiment' alt='lock' /></a>";
} else {
    // experiment is locked
    echo "<a href='app/lock.php?id=" . $data['expid'] . "&action=unlock&type=experiments'><img src='img/lock-gray.png' title='unlock experiment' alt='unlock' /></a>";
    // show timestamp button if it's not timestamped already
    if ($data['timestamped'] == 0) {
        echo "<a onClick=\"return confirmStamp()\" href='app/timestamp.php?id=" . $data['expid'] . "'><img src='img/stamp.png' title='timestamp experiment' alt='timestamp' /></a>";
    }
}
// TAGS
show_tags($id, 'experiments_tags');
// TITLE : click on it to go to edit mode only if we are not in read only mode
echo "<div ";
Beispiel #17
0
require_once 'inc/common.php';
$page_title = _('Export');
$selected_menu = null;
try {
    switch ($_GET['what']) {
        case 'csv':
            $make = new \Elabftw\Elabftw\MakeCsv($_GET['id'], $_GET['type']);
            break;
        case 'zip':
            $make = new \Elabftw\Elabftw\MakeZip($_GET['id'], $_GET['type']);
            break;
        case 'pdf':
            $make = new \Elabftw\Elabftw\MakePdf($_GET['id'], $_GET['type']);
            break;
        default:
            throw new Exception(_('Bad type!'));
    }
} catch (Exception $e) {
    require_once 'inc/head.php';
    display_message('error', $e->getMessage());
    require_once 'inc/footer.php';
    exit;
}
// the pdf is shown directly, but for csv or zip we want a download page
if ($_GET['what'] === 'csv' || $_GET['what'] === 'zip') {
    require_once 'inc/head.php';
    echo "<div class='well' style='margin-top:20px'>";
    echo "<p>" . _('Your file is ready:') . "<br>\n            <a href='app/download.php?type=" . $_GET['what'] . "&f=" . $make->fileName . "&name=" . $make->getCleanName() . "' target='_blank'>\n            <img src='img/download.png' alt='download' /> " . $make->getCleanName() . "</a>\n            <span class='filesize'>(" . Tools::formatBytes(filesize($make->filePath)) . ")</span></p>";
    echo "</div>";
    require_once 'inc/footer.php';
}