Webprofis is een Forum waarin je vragen kunt stellen die webgerelateerd zijn. Heb je vragen over of problemen met je Webpagina, HTML, CSS, Javascript, PHP of andere client of serverside scriptingtalen? Stel ze dan gerust op dit forum.
Op dit forum zijn een aantal vrijwilligers actief die u graag met uw vragen willen helpen en u waar mogelijk een passend antwoord aanbieden.
Hebt u zelf veel ervaring en kennis met betrekking tot het bovenstaande? U bent van harte welkom om uw kennis met anderen te delen!
We hopen dat eenieder op dit Forum een leerzame ervaring mag opdoen.
Team Webprofis
We hopen dat eenieder op dit Forum een leerzame ervaring mag opdoen.
Team Webprofis
simple filemanagement systeempje
ben bezig met een simple filemanagement systeempje; files uitlezen uit een folder en weergeven voor view, download en kunnen deleten. ieder heeft zijn eigen map die gemaakt wordt in de map
je kunt op het moment al een map aanmaken. Maar dan moet het verder: files uploaden naar de ndieuw aangemaate map en kijken en uitlezen de files uit de nieuwe aangemaakte map. Hoe krij g ik dat klaar?
dit is wat ik heb zover en hier heb ik het al geintegreerd in vanilla: http://develop3.webprofis.nl/sfm
users
. Deze mappen heb ik md5 gecodeerd. je kunt op het moment al een map aanmaken. Maar dan moet het verder: files uploaden naar de ndieuw aangemaate map en kijken en uitlezen de files uit de nieuwe aangemaakte map. Hoe krij g ik dat klaar?
dit is wat ik heb zover en hier heb ik het al geintegreerd in vanilla: http://develop3.webprofis.nl/sfm
/* vanilla variabelen */
$Session = Gdn::Session();
$UserName = md5($Session->User->Name);
/* einde vanilla variablen */
echo '<br /><br />';
echo '<h3><b>Upload bestanden</b></h3>';
if($_SERVER['REQUEST_METHOD'] == 'POST') {
$Session = Gdn::Session();
$UserName = md5($Session->User->Name);
// array met toegestane file extensies
$allowedExts = array("gif", "jpeg", "jpg", "png", "zip", "html", "htm", "js", "css", "less", "txt", "pdf");
$temp = explode(".", $_FILES["file"]["name"]);
$extension = end($temp);
// creeer map "users" als deze nog niet bestaat
$root = "/users/$UserName/";
if (!is_dir($root)) {
@mkdir("users/$UserName/", 0777);
if (($_FILES["file"]["size"] < 20000000) && in_array($extension, $allowedExts))
/* if ($_FILES['file']['error'] !== UPLOAD_ERR_OK) {
die("Upload failed with error " . $_FILES['file']['error']);
}
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $_FILES['file']['tmp_name']);
$ok = false;
switch ($mime) {
case 'image/jpeg':
case 'application/pdf'
case etc....
$ok = true;
default:
die("Unknown/not permitted file type");
}*/
{
// echo's als upload succesvol is
echo 'Status: upload succesvol!<br />';
echo 'Bestand: ' . $_FILES["file"]["name"] . '<br />';
$realname = $_FILES["file"]["name"];
echo 'Type: ' . $_FILES["file"]["type"] . '<br />';
echo 'Grootte: ' . ($_FILES["file"]["size"] / 1024) . ' kB<br />';
$data = explode(".",$_FILES["file"]["name"]);
//$newfilename = uniqid().".".end($data);
$newfilename = $realname;
move_uploaded_file($_FILES["file"]["tmp_name"], "users/$UserName/" . $newfilename);
// het pad naar het bestand dat geupload is; ervan uitgaande dat de map users in de root staat
echo '<br /><br />';
}
else
{
// echo als file extensie niet is toegestaan
echo "Niet toegestaan bestand";
}
}
else {
}
} // endif
if ($_POST["makedir"]) {
$dir = $_POST["dirname"];
@mkdir("users/$UserName/$dir", 0777);
}
?>
<style>
.delete a:before {
content: "\f1f8 ";
font-family: FontAwesome;
margin-right: 5px;
color: #333;
}
.view a:before {
content: "\f06e ";
font-family: FontAwesome;
margin-right: 5px;
color: #333;
}
.download a:before {
content: "\f019 ";
font-family: FontAwesome;
margin-right: 5px;
color: #333;
}
</style>
<form action="" method="post" enctype="multipart/form-data">
<div id="file_drop_target">
<input type="file" name="file" id="file" multiple />
</div>
<input type="submit" class="Button Primary" name="submit" value="Upload">
<br /><br />
<input type="text" name="dirname" id="dirname"><br /><br />
<input type="submit" class="Button Primary" name="makedir" value="Make dir">
</form>
<?php
/* functie aantal bytes omzetten naar Kb, Mb en Gb */
function sizeFormat($bytes){
$kb = 1024;
$mb = $kb * 1024;
$gb = $mb * 1024;
$tb = $gb * 1024;
if (($bytes >= 0) && ($bytes < $kb)) {
return $bytes . ' B';
} elseif (($bytes >= $kb) && ($bytes < $mb)) {
return ceil($bytes / $kb) . ' KB';
} elseif (($bytes >= $mb) && ($bytes < $gb)) {
return ceil($bytes / $mb) . ' MB';
} elseif (($bytes >= $gb) && ($bytes < $tb)) {
return ceil($bytes / $gb) . ' GB';
} elseif ($bytes >= $tb) {
return ceil($bytes / $tb) . ' TB';
} else {
return $bytes . ' B';
}
}
echo '<br /><br />';
// bestanden weergeven en Delete en Download links
$dir = "users/$UserName";
$files = scandir($dir);
sort($files);
echo '<table>';
?>
<tr>
<td><b>File</b></td>
<td><b>Size</b></td>
<td><b>View</b></td>
<td><b>Download</b></td>
<td><b>Delete</b></td>
</tr>
<?php
foreach ($files as $file) {
if ($file != '.' && $file != '..') { // mappen die linken naar bovenliggende folders niet weergeven
?>
<tr>
<td><?php
if(is_dir('users/'.$UserName.'/'.$file)) {
echo 'folder';
}
else {
echo 'bestand';
}
?>
</td>
<td><?php echo $file;?></td>
<td>
<?php echo sizeFormat(filesize($dir . '/' . $file));
?>
</td>
<td><?php echo "<div class='view'>"
."<a href='users/$UserName/$file' target='_blank'>View</a>"
."</div>";
?>
</td>
<td><?php echo "<div class='download'>"
."<a href='users/$UserName/$file' download>Download</a>"
."</div>";
?>
</td>
<td><?php if(isset($_GET['delete'])) {
unlink("users/$UserName/".$_GET['delete']);
$location = '/sfm';
header("Location: " . "http://" . $_SERVER['HTTP_HOST'] . $location);
}
echo "<div class='delete'>"
."<a href='?delete=".$file."'>Delete</a>"
."</div>";
?>
</td>
</tr>
<?php
}
}
echo '</table>';
Login of Registreer om te reageren.
Reacties
Verder md5 je twee keer de user (regel 3 en 15)
En verder snap ik van de rest ook niet echt veel en lijkt het me een totaal onbruikbaar (qua veiligheid) systeempje
De leesbaarheid is ook heel erg ver te zoeken, je output html code en daarin ga je weer met php html echoën.
php functies, php codes, html, css en alles door elkaar...
Wat betreft je vraag, uit de session haal je gewoon op wie wie is en laat die persoon gewoon uploaden naar zijn eigen map, het heeft geen zin om die meuk door een hash te halen, want ik mag aannemen dat die persoon zijn eigen map niet gaat proberen te hacken ?
Die md5 of eender welke hash je wilt gebruiken, is alleen nodig om het pad naar de werkelijke bestanden te "camoufleren" naar aanleiding van een eerdere vraag van je.
En als aanvulling zou ik niet alleen de bestandsnaam md5'en, maar dan daar ook weer iets mee doen, bijvoorbeeld
md5(datum van vandaag + filename)
Natuurlijk maakt het voor het voorbeeld weinig uit, maar voor de werkelijkheid moet je voor jezelf even iets unieks verzinnen.
$root = "/users/$UserName/";
in de if statement staat moest ik die nog ff herhalen. Ja oke, is niet nodig als ik die map al laat aanmaken voor het if statement; beetje dubbelop idd. Maar van de andere kant als ik die niet binnen het if statemaent laat maken, worden op voorhand al van iedereen mappen aangemaakt terwijl het pas nodig is als iemand daasdwerkelijk wat gaat uploaden. ben ik idd niet consequent in geweest; maar is ook nog maar proefprojectje; ga als het werkt alles netjes ordenen en html buiten de php tags zetten. Ja ook die style staat er tussendoor; wordt natuurlijk straks apart gezet ja de gedachtengang erachter: dat is idd ivm die download. je kutn het pad bekijken en iemand weet nu: aha, elke user heeft binnen map userszijn eigen map en daarin staan de bestanden. Je kunt de bestanden natuurlijk niet lezen omdat directory listing niet is toegestaan maar je zou wel kunnen beginnen met al te raden omdat je weet waar de bestanden staan. Vandaar die md5 op de mapnaam. Nu weet je nie meer welke mapnaam je medemember heeft omdat die in md5 gemaakt wordtDie forced download zit ik ook nog aan te denken.
Maar mijn eigenlijke vraag: ik kan bestanden uploaden en alles komt terecht in de map van de member (md5 map).
Ik wil het nu mogelijk maken dat ze mappen kunnen aanmaken en bestanden naar die speciefieke map kunnen uploaden.
En een submap aanmaken binnen een map en daarin ook bestanden kunnen uploaden.
Ik weet dat ik waarschijnlijk iets met recursie moet gaan doen. Heb verschillende soortelijk scripten ff ingezien en velen werken met een recursie om dat te realiseren. Maar dat is voor mij nog moeilijk om te begrijpen en te maken; die submappen en uploads in submappen dus
get voorbeeldje uit de losse pols Verder upload/delete/etc je gewoon op dezelfde manier (dus met variablen uit de url of uit een post)
edit: nu werkt ie, mits ingelogd: http://develop3.webprofis.nl/sfm
oke, ik ga ff dat scriptje hierboven bestuderen
Loop nu tegen 2 problemen aan:
Files die in subfolder staan kan ik niet deleten,. Wel als ze in de rootfolder van de user staan
Als je in een subfolder zit en je delete een file, krijg ik de header location niet goed zodat ie weer een refresh doet van de actuele pagina
Ik post het hele script hier maar als bijlage want is stukje langer gewroden:
je kunt het hier zien in werking, http://develop3.webprofis.nl/sfm
Let even niet op de beveiliging; script moet nog beveiligd worden, sanitize de input voor aanmaken directory etc...
Er staan ook her en der wat echos die ik gebruikt heb om te kijken waar ik zit in het path; ook ff nie t op letten
Dit kun je enkel oplossen om terug te gaan naar de parent dir, of als die niet (meer) bestaat daar de parent van.
Overignes, ik lees het pad uit vanuit de url: dan koppel ik die aan de var $dir
Op het moment dat ik dus op een open dirklik onder de folder, wordt via de url de url gekoppeld aan de $dir variable.
Dat werkt allemaal goed, ook de view en download, alleen die unlink in de subfolders niet
hetzelfde overignes voor het verwijderen van mappen: dit kan ook aaleen maar in de rootfolder van de users
Als ze niet leeg zijn moet je eerst de bestanden die erin staan verwijderen alvorens je de map kunt deleten.
Zoek daarvoor eens naar "delete folders php recursive" of iets in die strekking.
Wat de refresh betreft, doe eens gewoon zo:
Standaardd staat ie op:
$dir = 'uploads/sfm/'.$UserID;
als ik nu een submap heb bijvoorbeeld folder testfolder en ik zet de $dir bovenaan handmatig om naar:
$dir = 'uploads/sfm/'.$UserID.'/testfolder'
; gaat alles goed; hij leest alle bestanden in die subfolder en directories verwijderen en files verwijderen in die subfolder werk perfect.Dus het probleem zit hem in de manier waarop ik die $dir variable aanpas.
Nu doe ik het dus zo: ik lees de url uit; en pak het laatste gedeelte van de url achter het = teken en zeg dat de variable $dir daar in moet veranderen. En dan gaat het fout met het verwijderen van de mappen en files in subfolders. Damn; je hebt gelijk. Die mappen zijn niet leeg. Net even getest en wanner de map wel leeg is gooit ie de directory ook direct eruit. Deze net geprobeerd maar die geeft me wederom: Too many redirects; pagina wordt niet meer geladen
removeDirectory($dir.'/'.$_GET['delete']);
werkt nu perfect; volle mappen kunnen in zijn geheel verwijderd wordenDit is mijn unlink:
unlink($dir.'/'.$_GET['delete']);
Deze doet het alleen in de hoofdfolder.
Subfolders en files in subfolders kan ik niet verwijderen op deze manier.
Ik heb nu een folder
folder1
in de hofdmap staan met daarin Penguins.jpgZoals hierboven kan ik hem dus niet verwijderen.
Als ik de unlink zo neerzet verwijdert ie hem wel:
unlink("uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1/Penguins.jpg");
en zo ook:
unlink("uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1/".$_GET['delete']);
Enfin, de basename in huidige directory geeft me aan dat het folder1 is
Als ik
echo basename($dir);
doe krijg ik als output: folder1Dan zou je verwachten dat
unlink("uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/".basename($dir)."/".$_GET['delete']);
ook werkt maar NEE dus!!!
Waarom luistert ie niet naar basename($dir) terwijl als ik dit echo me exact folder1 output?
basename is natuurlijk onderdeel van $dir var maar je ziet dat het met basename al fout gaat.
Logisch dat het met $dir dan ook fout gaat. Maar waarom gebeurt dit alleen in de submappen?
In de hoofdmap gaat het wel gewoon goed
Ik vraag dit, omdat je in bovenstaande VB één bestandje wil verwijderen
ja bij het deleten van de map roep ik die aan ja. Maar die heeft toch geen invloed op deleten van bestanden?
In de hoofdmap heb ik Penguins.jpg staan.
In de subfolder Folder1staat ook Penguins.jpg
Delete ik die Penguins.jpg in de subfolder, dan gooit ie de penguins bij de hoofdmap eruit en in de submap blijven ze staan
Dat wil dus zeggen: hij weet dat ie Penguins.jp moet deleten en dat gebeurt ook; alleen gooit ie ze in de verkeerde map eruit
vanaf regel 25
je vergeet het hele pad in je link....
?delete=pad/file
develop3.webprofis.nl/sfm?delete=uploads/hash/folder1/Penguins.jpg
Dat zou dus moeten werken maar helaas er gebeurt niets; penguins.jpg blijft gewoon staan in folder1
Nu gooit ie de penguins noch in de hoofdmap, noch in de submap eruit
Er gaat dus iets fout met die unlink(); als ik in een submap sta kan ie blijkbaar niet in submappen verwijderen, alleen in de hoofdmap.
Dus als ik een submap ben is dit:
unlink($dir.'/'.$_GET['delete']);
blijkbaar niet hetzelfde als dit:unlink("uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1/".$_GET['delete']);
Want bij de laatste gooit ie hem wel uit de submap eruit
uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1
Bij elke bestandje heb ik deze output
ik snap hier helemaal niets van:
Dit is de unlink:
unlink($dir.'/'.$_GET['delete']);
Als ik $dir echo; zie output hierboven
/ en GET delete erachter en er staat dus zoiets als:
uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1/Penguins.jpg
Dus:
unlink($dir.'/'.$_GET['delete']);
levert: unlink(uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1/Penguins.jpg);Maar dit klopt toch ook eigenlijk niet?
Een unlink moet toch altijd beginnen met " ?
unlink("pad/naar bestand/file.jpg");
zoals het hier staat:
unlink($dir.'/'.$_GET['delete']);
levert het dus eigenlijk dit op:unlink(uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1/Penguins.jpg);
-> zonder dubbele quotesMaar dit werkt evengoed niet: Edit: dit werk overigens ook:
unlink('uploads/sfm/'.$UserID.'/folder1/'.$_GET['delete']);
het probleem zit hem dus in folder1
Hij ziet de submap niet; daarom gooide hij penguins bij d e hoofmap eruit terwijl ik hem in folder1 wilde deleten
Dat is dus duidelijk het bewijs dat ie het pad ziet naar het bestand zonder submap
(string)$dir
Maar doe het eens anders, want dit schiet niet echt op zo
Doe eens zo iets:
uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/folder1
als ik deze die() gebruik: krijg ik deze output:
uploads/sfm/c4ca4238a0b923820dcc509a6f75849b/Penguins.jpg
dit gooit het bestand uit de submap: Maar tevens ook uit de hoofdmap als daar hetzelfdee bestand in staat
Jij gebruikt dus niet het hele pad naar de file om te verwijderen!
$_GET['delete'] zou het complete pad moeten bevatten!
url.com?delete=pad/naar/file.ext
Wat ik steeds heb gedacht:
die
$_GET['delete']
leest de file.In de unlink staat het pad al klaar; er hoeft alleen de file nog achter geplakt te worden.
Dat was mijn logica. Maar zo werkt het dus niet.
Wat een drama, hier heb ik een paar dagen op gezeten op deze onzin...
Maar zeeeeeeeeeeer hartelijk dank voor het meedenken.
zo werkt het dus:
."<a href='?delete=".$dir.'/'.$file."'></a>"
en dan als het een folder betreft:
removeDirectory($_GET['delete']);
en als het een file is:unlink($_GET['delete']);
Dit is hem dus: Todo's:
- header location nog in orde maken zodat ie op de pagina blijft hangen als je iets verwijderd
- breadcrumbs maken zodat ze kunnen navigeren door de mappen
- de storage balk recursive maken zodat ie ook de storage in de submappen meetelt
- de input nog beveiligen van makedir
- de url nog beveiligen zodat ze bij http://develop3.webprofis.nl/sfm?dir=uploads/sfm/ niet de inhoud van uploads te zien krijgen en al zeker niet van dir=uploads/
Als er een fout in de url staat, dan kom je nog altijd in de hoogste bestaande dir uit.
Deze meuk natuurlijk toe te passen NADAT je verwijderd hebt.
ook altijd een exit gebruiken na header location!!, verder hoef je al die meuk die jij in je header stopt er niet in te doen, dat kan vele malen korter en leesbaarder door gewoon:
Wat ik bedoel met fouten in de url....beetje uitleg
Als je een mapstructuur hebt bijvoorbeeld map1, met daarin map2 en in map2 zit map3
je gaat naar ?delete=map1/map3/map2, wat dus feitelijk niet bestaat, dan kom je uit op map1/map2/ (hij haalt 3 er gewoon tussenuit) en houd dus map1/map2 over, want die bestaat wel degelijk.
Een klein beetje raar misschien, en wil je dat niet, dan kun je een else inbouwen en wel zo:
Met soortgelijke code kun je overigens ook je breadcrum genereren.
bestandjes verwijderen uit subfolder gaat alleen als er in de hoofdmap minimaal 1 bestandje staat. Bevat de hoofdmap alleen een map, dan kan ik geen files uit de subfolders verwijderen. Directories in submappen kan ik wel verwijderen ongeacht of de hoofdmap een bestand bevat of niet. Hoe kan dat in hemelsnaam?
Zet sowieso alle locationheaders uit, en dump zoveel data als mogelijk op je scherm, om zo te gaan elimineren wat er fout kan gaan.
En zet sowieso de error reporting volle bak!
Overigens: ik heb het nu zo staan: Als ik direct na die header een die(); zet, verwijdert ie geen files meer; zonder de die() wel