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')); }
/** * 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)); }
/** * 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>"; } }
<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']);
// 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>";
$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.";
* 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']; }
$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'";
$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');
/** * 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!'); } }
/** * 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>"; }
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 {
/** * 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>"; } }
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'
$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";
} // 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 ";
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'; }