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

simple filemanagement systeempje

2

Reacties

  • bewerkt di 3 mei 2016
    PMPosts: 879
    ja het probleem is ik kan geen error_reporting aanzetten omdat ik binnen het vanillaframe zit. Dan krijg ik pagina: something is wrong
    maar net ff getest met een .txt bestandje in de hoofdmap dat alleen een dot bevat: dat is al genoeg; dan werkt alles
  • regel 7 lijkt me sowieso vaag...

    if(is_dir($dir.'/'.$file)){

    Een file is nooit een dir he.
  • bewerkt di 3 mei 2016
    PMPosts: 879
    Dit is mijn foreach:
    foreach ($files as $file) {
    if ($file != '.' && $file != '..') { // don't show links to previous folders
    $MimeFileType = mime_content_type($dir.'/'.$file);
    $FileExtension = pathinfo($file, PATHINFO_EXTENSION);
    $ClassExtension = 'sfm_'.$FileExtension;
    Alles bestanden, of het nu dirs of files zijn worden gezien als $file; daarom een extra check als $file een dir is of als dat niet nis
  • PMPosts: 879
    ik zal het complete bestand nog ff meesturen zoals het nu is:
    zip
    zip
    sfm.zip
    4K
    sfm.zip 4.1K
  • Zet nu gewoon bij elke actie dat er moet gebeuren een echo en zet de header location uit
    if($voorwaarde1)
    {
    echo 'voorwaarde1 = '.$voorwaarde1.' dus...whatever<br>';
    if(!doeIets())
    {
    echo 'doeIets() returnd false....waarom?<br>';
    }
    }
    else
    {
    echo 'voorwaarde1 werd niet voldaan want '.$voorwaarde1.' is ... whatever<br>';
    if(!doeIets())
    {
    echo 'doeIets() returnd false....waarom?<br>';
    }
    }
    Ik weet niets van vanilla af, maar een beetje gaar vind ik het wel als je die error reporting niet aan kunt zetten...
    Je kunt er waarschijnlijk zelf wel een maken? Al zou ik gewoon localhost eerst alles maken, en daarna pas integreren in vanilla!
    1000 keer sneller en je hebt alles voor het zeggen ;-)
  • bewerkt di 3 mei 2016
    PMPosts: 879
    ja vreemd; er hoeft dus blijkbaa niet perse een bestandje in de hoofdmap te staan, een map is ook al voldoende.
    Maw: staat er in de hoofdfolder slechts 1 map waarin submappen en daarin files, dan kan ik die files er niet uitgooien.
    Staat er een map in een subfolder, dan kan ik die wel eruitgooien.

    Maak ik in de hoofdfolder een 2e map aan of load een file up, dan kan ik wel files uit subfolders verwijderen. En mappen natuurlijk ook, maar dat kon ik zowieso al
    Er moet dus minimaal een 2e map of een file in de hoofdfolder staan wil ik files uit subfolders kunnen verwijderen
  • bewerkt di 3 mei 2016
    PMPosts: 879
    de total size bij mekaar tellen van alle files heb ik nu ook werkend:
    $MainDir = 'uploads/sfm/'.$UserID;
    /* Calculate used storage */
    $iterator = new RecursiveIteratorIterator(
    new RecursiveDirectoryIterator($MainDir)
    );
    if (is_dir($MainDir)) {
    $SumStorage = 0;
    foreach ($iterator as $file) {
    $SumStorage += $file->getSize();
    }
    $UsedStorage = $SumStorage/$LimitStorage*100;
    }
    Deze telt vanaf de hoofdmap de size van alle files samen; inclusief wat er in subfolders staat
  • nuet schreef:: ja vreemd; er hoeft dus blijkbaa niet perse een bestandje in de hoofdmap te staan, een map is ook al voldoende.
    Maw: staat er in de hoofdfolder slechts 1 map waarin submappen en daarin files, dan kan ik die files er niet uitgooien.
    Staat er een map in een subfolder, dan kan ik die wel eruitgooien.

    Maak ik in de hoofdfolder een 2e map aan of load een file up, dan kan ik wel files uit subfolders verwijderen. En mappen natuurlijk ook, maar dat kon ik zowieso al
    Er moet dus minimaal een 2e map of een file in de hoofdfolder staan wil ik files uit subfolders kunnen verwijderen
    mjah, ik weet wel een schapenzak manier om dit op te lossen dan.....
    Maak gewoon de htaccess file gelijk aan per userDir waarin je directory listing etc regels...en zorg dat die file niet gezien wordt.
    Maar dat vind ik echt een schapezak oplossing (want het is een gaar gegeven, wat vast ergens nog haken of ogen vertoont!!), maar in dit geval kun je er je gemak/voordeel mee doen... :/
  • PMPosts: 879
    die breadcrumbs wrken perfect @vinTage
    Moet alleen nog ff de uploads directory en sfm directory eruithalen en dan de hash van de userID vervangen door Root of Home of zoiets
  • PMPosts: 879
    hmmm...heb een probleem met die breadcrumbs. Ze werken perefect, maar ik kan die foreach pas plaatsen nadat de files gerendered zijn.
    Doe ik het ervoor, dan gooit ie de ankers van de folders eruit en de size van de files geeft ie nie t meer weer.
    dus die breadcrumbs staan nu onder de files. Die moeten natuurlijk erboven komen te staan. Hoe a ik dat oplossen?
  • Lijkt mij sterk.....
    Die foreach van de breadcrumb gebruikt alleen de url en verder niets...
  • PMPosts: 879
    Ik had ff gehoopt om die crumbs in een div te gooien en met position absolute ze naar boven te trekken maar die file list is bij iedereen niet even lang. dus die vogel gaat niet op
  • PMPosts: 879
    ja dit zal als standalone beslist werken maar binnen het framewerk gebeurenn er soms rare dingen
  • bewerkt wo 4 mei 2016
    PMPosts: 879
    Deze kan ik wel boven de files zetten zonder dat het invloed heeft op de files maar hoe krijg ik hier de ankers nu in?
    $crumbs = explode("/",$_SERVER["REQUEST_URI"]);
    foreach($crumbs as $crumb){
    echo str_replace(array(".php","_"),array(""," "),$crumb) . ' / ';
    }
  • PMPosts: 879
    geen idee waarom dat de andere onder de files moest staan, deze werkt in ieder geval perfect en hij kan boven de files staan.
    // BREADCRUMBS 
    $crumbs = explode('/', $dir);
    $url_pre = '';

    foreach($crumbs as $crumb){
    $url_pre .= $crumb;
    echo '<a href="?dir='.$url_pre.'">'.str_replace(array("uploads","sfm","$UserID"),array(" "," ","Root"),$crumb).' / '.'</a>';
    $url_pre .= '/'; // add this after you echo the link, so that dir doesn't start with a /
    }
    De array haalt de uploads en sfm uit de breadcrumbs en vrandert de hash in Root
    Enige is dat ik nu 2 // aan het begin heb die ik er eigenlijk nog uit wil hebben.
  • PMPosts: 879
    Breadcrums klaar en werken perfect:
    // BREADCRUMBS 
    $crumbs = explode('/', $dir);
    $crumbDir = '';

    foreach($crumbs as $crumb){

    $crumbDir .= $crumb;
    if($crumb != 'uploads' and $crumb != 'sfm') { // de 2 slashes van uploads en sfm eruit filteren
    echo '<a href="?dir='.$crumbDir.'">'.str_replace(array("uploads","sfm","$UserID"),array(" "," ","Root"),$crumb).' / '.'</a>';
    }
    $crumbDir .= '/'; // dir moet niet starten met een /

    }
    Volgende:
    de url moet beveiligd worden:
    Dit: http://develop3.webprofis.nl/sfm?dir=uploads/
    en http://develop3.webprofis.nl/sfm?dir=uploads/sfm/ en http://develop3.webprofis.nl/sfm?dir=. moet allemaal niet meer mogelijk zijn
  • bewerkt do 5 mei 2016
    PMPosts: 879
    heb een functie gevonden die de url beschermd:
       /* PROTECT URL */

    $protectedDirectories = array(
    array( 'uploads', 'sfm', $UserID )
    );
    $directory = str_replace('\\','',$_GET['dir']);
    $directory = trim($directory,'/');
    $directory = preg_replace('#[\/]{1,}#','/',$directory);
    $stats = false; // True = Protected , False = Cannot enter this directory.
    $seperate = explode('/',$directory);
    $cntSeperate = count( $seperate );

    foreach($protectedDirectories as $pattern ){
    if( count( $pattern ) > $cntSeperate ){
    continue;
    }
    $innerStats = true;

    foreach( $pattern as $key => $val ){
    if( $seperate[ $key ] !== $val ){
    $innerStats = false;
    break;
    }
    }
    if( $innerStats == false ){
    continue;
    }
    $stats = true;
    break;
    }

    if( $stats == true ) {

    // echo 'allowed'; // voor te testen

    }
    elseif ($_SERVER['QUERY_STRING'] != 'p=sfm') {


    // echo 'no access';
    $location = '/sfm';
    header("Location: " . "http://"; . $_SERVER['HTTP_HOST'] . $location);
    die();

    }

    /* END PROTECT URL */
    Dit werkt goed, alleen moet ik nog de deletestring die gemaakt wordt als je delete toestaan. Want deze wordt nu ook geblocked
  • bewerkt do 5 mei 2016
    PMPosts: 879
    oke dan, heb voor de delete url string een uitzondering gemaakt;
    regel 37 hierboven is:
     elseif ($_SERVER['QUERY_STRING'] != 'p=sfm' and strpos($_SERVER['QUERY_STRING'], 'delete=uploads/sfm/'.$UserID) != true) {
    Maw: elke delete string bevat minimaal 'delete=uploads/sfm/'.$UserID
    Die toestaan. Alle andere deletes zijn al beveiligd en worden ook niet toegestaan
  • bewerkt di 10 mei 2016
    PMPosts: 879
    het enige wat ik nu nog moet doen is bij het aanmaken een extra bestandje meesturen dat hidden is. Ivm deleten files uit subfolder. Ja idioot natuurlijk dat dat zo moet, maar ik weet ff geen andere oplossing.
    De rest heb ik uitvoerig getest. Alle scenarios doorgelopen en zover ik kan overzien werkt alles naar behoren.
    Als iemand zin heeft om nog ff wat scenarios te testen, graag! Kan best hier en daar nog wat bugs tegenkomen.
    http://develop3.webprofis.nl/sfm (wel eerst inloggen) :)
  • bewerkt di 10 mei 2016
    PMPosts: 879
    folders kun je nu downloaden; ze worden ingezipped en direct als forced download naar de brwoser gestuurd. Hieronder de functie van zippen:
    /* FUNCTION ZIP DIR */
    function Zip($source, $destination)
    {
    if (!extension_loaded('zip') || !file_exists($source)) {
    return false;
    }

    $zip = new ZipArchive();
    if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
    return false;
    }

    $source = str_replace('\\', '/', realpath($source));

    if (is_dir($source) === true)
    {
    //$zipfiles = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
    $zipfiles = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::LEAVES_ONLY);


    foreach ($zipfiles as $zipfile)
    {
    $zipfile = str_replace('\\', '/', $zipfile);

    // Ignore "." and ".." folders
    if( in_array(substr($zipfile, strrpos($zipfile, '/')+1), array('.', '..')) )
    continue;

    $zipfile = realpath($zipfile);

    if (is_dir($zipfile) === true)
    {
    $zip->addEmptyDir(str_replace($source . '/', '', $zipfile . '/'));
    }
    else if (is_file($zipfile) === true)
    {
    $zip->addFromString(str_replace($source . '/', '', $zipfile), file_get_contents($zipfile));
    }
    }
    }
    else if (is_file($source) === true)
    {
    $zip->addFromString(basename($source), file_get_contents($source));
    }

    return $zip->close();
    }
    En hier de download:
    // DOWNLOAD
    if(isset($_GET['compress'])) {

    $tmpfolder = 'uploads/sfm/'.$UserID.'/tmpzip';
    if (!is_dir($tmpfolder)) {
    @mkdir($tmpfolder, 0777, true);
    }

    // compress folder and sent compressed zip to plugins/sfm/views
    Zip($_GET['compress'], $tmpfolder."/compressed.zip");

    if(file_exists($tmpfolder.'/compressed.zip')){
    // set example variables
    $filename = "compressed.zip";
    $filepath = $tmpfolder."/";

    // http headers for zip downloads
    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"".$filename."\"");
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($filepath.$filename));
    //ob_end_flush();
    while (ob_get_level()) {
    ob_end_clean();
    }
    @readfile($filepath.$filename);
    unlink($tmpfolder.'/compressed.zip'); // unlink compressed.zip
    rmdir($tmpfolder); // remove tmpdir
    die();

    }


    }

    if(!is_dir($dir.'/'.$file)){

    echo "<div class='download'>"
    ."<a href=" . $dir . "/" . $file . " download></a>"
    ."</div>";

    }
    else {

    echo "<div class='download'>"
    ."<a href='?compress=".$dir.'/'.$file."'></a>"
    ."</div>";

    }
    Wordt tijdelijk ff een map aangemaakt: tmpzip waarin de compressed.zip gezet wordt die na de download ook weer direct verwijderd wordt zodat de map tmpzip niet tussen de andere mappen komt te staan in de lijst
  • PMPosts: 879
    Ik zat nog te denken om files te kunnen renamen. Maar is dat niet een groot risico?
    je kunt nu geen .php files uploaden omdat de extensie niet in de array staat. Maar wat als iemand nu een php bestand op zijn pc heeft die bijv heet: test.php en die hernoemt op zijn pc naar test.jpg.
    Vervolgens gaat ie test.jpg uploaden en eenmaal geupload hernoemt ie hem terug tot test.php. En laten we even uitgaan van worst case scenario: in test.php staat een unlink()
    Maw: als je renamen toestaat kan iemand je zoiets flikken toch?
  • bewerkt wo 11 mei 2016
    PMPosts: 415
    Je kunt gewoon de extentie controleren tijdens het renamen en kijken of die in het $allowed array voorkomt...if not, rename = false

    of nog beter, je zorgt dat de extentie helemaal niet aangepast kan worden.
    nuet
  • PMPosts: 879
    heb unzip functie toegevoegd:
    if(isset($_GET['extract'])) {
    $zip = new ZipArchive;
    if ($zip->open($_GET['extract']) === TRUE) {

    $zip->extractTo(dirname($_GET['extract']));

    $zip->close();

    }
    // do a refresh
    $tree = explode('/', $_GET['extract']);
    $treeDir = '';
    foreach($tree as $dir) {
    if(is_dir($treeDir.$dir) && !empty($dir)) {
    $treeDir .= $dir.'/';


    }
    }

    //header location and remove last / from url
    header ("Location: ".'?dir='.rtrim($treeDir, "/"));

    }
    en het anker:
    elseif(in_array($FileExtension,array('zip'))) {
    echo "<div class='unzip'>";

    echo "<a href='?extract=".$dir.'/'.$file."'></a>";
    echo "</div>";
    }
    Nu zit ik te denken: stel iemand heeft een .php file ingezipped. Bij extracten komt er dus een .php file vrij dat niet mag gebeuren.
    \Wat is meest logisch om dit te controleren: je kunt denk ik niet in een zip folder kijken en zeggen: dat .php filetje wordt niet extract?
    Of wel extracten en kijken als er .php file is in de dir, die direct unlinken?
  • bewerkt do 12 mei 2016
    PMPosts: 879
    ik heb hem al werkend:
    if(isset($_GET['extract'])) {
    $zip = new ZipArchive;
    if ($zip->open($_GET['extract']) === TRUE) {
    for ($i = 0; $i < $zip->numFiles; $i++) {
    $path_info = pathinfo($zip->getNameIndex($i));
    $ext = $path_info['extension'];

    if(in_array($ext, $AllowedExts)) { // only files with allowed Exts can be extracted
    $zip->extractTo(dirname($_GET['extract']), $zip->getNameIndex($i)); // extract in the same folder as where the zip file is
    }
    }
    $zip->close();
    }
  • bewerkt vr 13 mei 2016
    PMPosts: 879
    heb nog vraagje over de delete:
     // DELETE

    if(isset($_GET['delete'])) {

    // if is directory -> remove dir
    if(is_dir($dir.'/'.$file)){

    //rmdir($dir.'/'.str_replace(['/', '\\', '..'], '', $_GET['delete'])); // already protected
    removeDirectory($_GET['delete']);

    }
    // else (must be a file) -> unlink file
    else {

    //unlink($dir.'/'.str_replace(['/', '\\', '..'], '', $_GET['delete'])); // already protected
    unlink($_GET['delete']);

    }
    // do a refresh
    $tree = explode('/', $_GET['delete']);
    $treeDir = '';
    foreach($tree as $dir) {
    if(is_dir($treeDir.$dir) && !empty($dir)) {
    $treeDir .= $dir.'/';
    }
    }

    //header location and remove last / from url
    header ("Location: ".'?dir='.rtrim($treeDir, "/"));


    }

    // echo delete anchor
    echo "<div class='delete'>"
    ."<a href='?delete=".$dir.'/'.$file."'></a>"
    ."</div>";

    Zo staat ie nu in de foreach.
    Als ik header ("Location: ".'?dir='.rtrim($treeDir, "/")); hierboven uitcomment, schiet ie terug naar de webroot. Hoe kan ik dat voorkomen? Hij zou eigenlijk op de pagina (met bijvoorbeeld de submap) moeten blijven staan. Ik wil nl een AJAX reload gebruiken
  • bewerkt vr 13 mei 2016
    PMPosts: 415
    Hoe kan het dat hij naar de webroot gaat??
    Dan heb je vast elders een header location, want bovenstaande code zegt nergens dat je moet redirecten als je de header uitcomment!
    Hij zou dan gewoon op url.com?delete=meukHier moeten blijven staan!

    En nogmaals, zet een exit na een header location! Dit zou namelijk wel eens de oplossing voor je redirrect kunnen zijn...
  • bewerkt vr 13 mei 2016
    PMPosts: 879
    je hebt gelijk, ik had deze niet gezien op regel 45
    /* PROTECT MANIPULATING VIA URL */
    $protectedDirectories = array(
    array( 'uploads', 'sfm', $UserID )
    );
    $directory = str_replace('\\','',$_GET['dir']);
    $directory = trim($directory,'/');
    $directory = preg_replace('#[\/]{1,}#','/',$directory);
    $stats = false; // True = Protected , False = Cannot enter this directory.
    $seperate = explode('/',$directory);
    $cntSeperate = count( $seperate );

    foreach($protectedDirectories as $pattern ){
    if( count( $pattern ) > $cntSeperate ){
    continue;
    }
    $innerStats = true;

    foreach( $pattern as $key => $val ){
    if( $seperate[ $key ] !== $val ){
    $innerStats = false;
    break;
    }
    }
    if( $innerStats == false ){
    continue;
    }
    $stats = true;
    break;
    }

    if( $stats == true ) {

    //echo 'allowed';

    }

    // we make an exception when url = /sfm and when in the url is a delete, compress or extract string, which contains at least: delete=uploads/sfm/'.$UserID
    elseif ($_SERVER['QUERY_STRING'] != 'p=sfm'
    and strpos($_SERVER['QUERY_STRING'], 'delete=uploads/sfm/'.$UserID) != true
    and strpos($_SERVER['QUERY_STRING'], 'compress=uploads/sfm/'.$UserID) != true
    and strpos($_SERVER['QUERY_STRING'], 'extract=uploads/sfm/'.$UserID) != true ) {

    //echo 'no access';
    $location = '/sfm';
    header("Location: " . "http://"; . $_SERVER['HTTP_HOST'] . $location);
    die();

    }

    /* END PROTECT URL */
    Bij de delete heb ik de die() achter de header location gezet maar dan verwijdert ie het bestand niet bij deleten:
    header ("Location: ".'?dir='.rtrim($treeDir, "/"));
    die();
    Als ik de header location helemaal weghaal en ook die die() erachter, verwijdert ie het bestand wel maar schiet terug naar de root. En de andere header location in de protect url hb ik al weggeaald. In de url blijft idd staan: sfm?delete=....blabla.... maar geeft de bestanden in de root weer.
    Logisch denk ik ook want als je in een subfolder staat is de url altijd iets van: sfm?dir=uploads/sfm/hash/ folder1/subfolder1...
    en omdat de url nu delete=......laat ie de root weer zien

    Hieronder is het complete bestand:

    zip
    zip
    sfmphp.zip
    6K
    sfmphp.zip 6.1K
  • die() is niet hetzelfde als exit.

    Verder heb je zomaar wat ifjes in je code staan, maar dat is niet de manier i.m.h.o.
    Want zo kun je zoals je nu voorhebt, dus inderdaad aan meerdere voorwaarden voldoen en dus onjuiste meuk te zien krijgen.

    Zo (iets) hoort het
    if(a)
    {
    doe a
    }
    elseif(b)
    {
    doe b
    }
    elseif(c)
    {
    doe c
    }
    else
    {
    default meuk..
    }
    of iets met een switch kan ook...legio van manieren, zolang het maar gestructureerd is en niet werkt met random ifjes

    En je moet nu nog niet denken aan ajax, EERST moet alles werken ZONDER javascript, pas als ALLES werkt MET JUISTE FOUTAFHANDELING ETC, moet je pas de gebruiker(browser) erbij gaan betrekken!
  • bewerkt vr 13 mei 2016
    PMPosts: 879
    die(); is toch equivalent to exit(); ??
  • bewerkt vr 13 mei 2016
    PMPosts: 415
    Nee Ik dacht van niet, ff zoeken :p

    edit, oh, blijkbaar wel, ik heb dat altijd verkeerd begrepen :open_mouth:
Login of Registreer om te reageren.