[PHP] File upload systeem

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • bindsa
  • Registratie: Juli 2009
  • Niet online
In één van m'n webapps heb ik momenteel een file sharing systeem draaien, die wil ik gaan refactoren, alleen ik loop tegen een paar problemen aan. De huidige versie werkt als volgt:

- Bestand wordt geupload
- PHP hasht de bestandsnaam + random string zodat je een unieke bestandsnaam krijgt
- Dat bestand wordt in een dir geplaatst
- De originele bestandsnaam + de nieuwe naam gaan in een MySQL db en ze krijgen een id mee
- Als een user dan een bestand opvraagt gaat dat als volgt:
- De user klikt op een link met parameters in de url (de fileid staat in de url)
- Bestandsnaam wordt opgehaald van de db
- PHP leest bestand en flusht het naar de user

Werkt op zich allemaal prima, maar nu zou ik graag willen dat het allemaal wat afgeschermder was. Door een simpel index.php bestandje in de file dir te plaatsen voorkom ik al dat de lijst met bestandsnamen zichtbaar is. Maar ik zou ook graag willen dat direct linking over de URL helemaal uitgesloten wordt (ik wil niet dat iedereen elkaars bestanden zomaar kan downloaden).

Een paar opties die ik bedacht heb:
- .htaccess enz. -> geen optie, de app moet op nagenoeg alle hosts kunnen draaien (dus ook op hosts waar je geen custom .htaccess mag hebben)
- Upload inlezen en wegschrijven naar de MySQL en daar opslaan in een BLOB veld ofzo. Maar iets zegt mij dat dat een ranzige oplossing is, vraagt nogal wat resources van de database
- De bestanden opslaan op een machine die voor PHP wel bereikbaar is, maar die niet direct in verbinding staat met het internet -> ook geen optie, zelfde reden als de eerste optie

Weet iemand een andere oplossing?

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Waarom zou je die bestanden uberhaupt online bereikbaar hebben staan, als je ze toch via PHP van je filesystem uitleest en via PHP naar de user retourneert?

Acties:
  • 0 Henk 'm!

  • Lye
  • Registratie: Januari 2010
  • Laatst online: 16:10

Lye

Of de bestanden buiten de public_html map halen, of toch .htaccess. Naar mijn weten zijn dat de enige manieren om bestanden te beschermen van publieke toegang..

Acties:
  • 0 Henk 'm!

  • bindsa
  • Registratie: Juli 2009
  • Niet online
Osiris schreef op donderdag 20 mei 2010 @ 20:10:
Waarom zou je die bestanden uberhaupt online bereikbaar hebben staan, als je ze toch via PHP van je filesystem uitleest en via PHP naar de user retourneert?
Omdat het dus gaat om een Webapp die als pakket zal gaan worden verkocht en op nagenoeg alle PHP hosts moet draaien (vergelijk het maar met bijv. Wordpress)

Ik zat zelf nog te denk aan het volgende:

Ik maak voor elke file een .php bestand aan, daarin zet ik het volgende:
PHP:
1
$file = filecontents;

Waarbij ik bij filecontents de inhoud van het bestand wegschrijf. Zo ziet een eventuele direct linker helemaal niets. Is dat een goed plan?

[ Voor 26% gewijzigd door bindsa op 20-05-2010 20:36 ]


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Iedere webserver heeft toch wel een manier om content van de grote boze buitenwereld af te schermen, zonder dat ze onbereikbaar worden voor PHP? Bijv door het onder de directory htdocs of public_html te plaatsen, maar zodat je er met ../../ of iets dergelijks nog wel bij kunt?

Acties:
  • 0 Henk 'm!

  • TheWickedD
  • Registratie: Juli 2002
  • Laatst online: 02-04-2024
Als ik het goed begrijp is de "nieuwe bestandsnaam" waaronder het bestand op de schijf staat 1) behoorlijk random en 2) nooit zichtbaar voor de eindgebruiker (want die heeft de sql id in de link en krijgt vast het betsand met de originele naam teruggestuurd). niet zo'n probleem dus!

Dit is natuurlijk security through obscurity en als men genoeg van je hash afweet kun je het vast bruteforces door alle mogelijke random bestandsnamen op te vragen... Anders idd buiten de public_html zetten, dat moet toch kunnen op elke redelijke host (of verkijk ik me daarop)?

Acties:
  • 0 Henk 'm!

  • TheWickedD
  • Registratie: Juli 2002
  • Laatst online: 02-04-2024
L0calh0st schreef op donderdag 20 mei 2010 @ 20:34:
Ik zat zelf nog te denk aan het volgende:

Ik maak voor elke file een .php bestand aan, daarin zet ik het volgende:
PHP:
1
$file = filecontents;

Waarbij ik bij filecontents de inhoud van het bestand wegschrijf. Zo ziet een eventuele direct linker helemaal niets. Is dat een goed plan?
Ik denk dat dat geen oplossing is voor bestanden niet in tekstformaat zijn opgeslagen, denk dat je een binary bestand zo goed door de war kan halen. I.i.g als je geen vuile truucjes wilt uithalen moet je het buiten de public_html zetten. Je kan ook de user van je app de directory voor de bestanden zelf kunnen laten zet. Me daar de duidelijke warning dat bestanden in de public_html eventueel direct benaderbaar zijn en dat deze directory dus beter erbuiten kan worden gehouden. Dan is het de keuze aan de gebruiker hoe veilig ze willen zijn (zorg wel voor een veilige default natuurlijk)

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
L0calh0st schreef op donderdag 20 mei 2010 @ 20:34:
Waarbij ik bij filecontents de inhoud van het bestand wegschrijf. Zo ziet een eventuele direct linker helemaal niets. Is dat een goed plan?
Nee. Je denkt nu enkel aan smerige pleisters. Het echte probleem is de locatie van de files, en die kan zelfs bij de meest povere 1 euro per maand hosting gewoon buiten de webroot. :z

{signature}


Acties:
  • 0 Henk 'm!

  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 10:21
TheWickedD schreef op donderdag 20 mei 2010 @ 20:41:
Als ik het goed begrijp is de "nieuwe bestandsnaam" waaronder het bestand op de schijf staat 1) behoorlijk random en 2) nooit zichtbaar voor de eindgebruiker (want die heeft de sql id in de link en krijgt vast het betsand met de originele naam teruggestuurd). niet zo'n probleem dus!

Dit is natuurlijk security through obscurity en als men genoeg van je hash afweet kun je het vast bruteforces door alle mogelijke random bestandsnamen op te vragen... Anders idd buiten de public_html zetten, dat moet toch kunnen op elke redelijke host (of verkijk ik me daarop)?
Als je de bestandsnamen flink random maakt (GUID ofzo), is dat volgens mij een goede oplossing. Op het eerste gevoel is dat inderdaad security through obscurity, maar eigenlijk is er geen wezenlijk verschil met een logincombo. 128Bits is niet zomaar te brute-forzen. Eventueel doet je 2 guids.

Enig nadeel is natuurlijk als er ergens een linkje online staat of iets dergelijks. Dit is dan hetzelfde als je logincombo online zetten, maar dit zullen veel mensen niet doorhebben.

Acties:
  • 0 Henk 'm!

  • bindsa
  • Registratie: Juli 2009
  • Niet online
apokalypse schreef op donderdag 20 mei 2010 @ 21:09:
[...]

Als je de bestandsnamen flink random maakt (GUID ofzo), is dat volgens mij een goede oplossing. Op het eerste gevoel is dat inderdaad security through obscurity, maar eigenlijk is er geen wezenlijk verschil met een logincombo. 128Bits is niet zomaar te brute-forzen. Eventueel doet je 2 guids.

Enig nadeel is natuurlijk als er ergens een linkje online staat of iets dergelijks. Dit is dan hetzelfde als je logincombo online zetten, maar dit zullen veel mensen niet doorhebben.
Hier heb je een punt. Dus als ik in de HTML alleen de file ID laat zien, de namen hash en de downloads met de originele naam aanbiedt (en dit alles dan gekoppeld over de database) moet het redelijk veilig zijn?

Natuurlijk moet ik dan nog wel een index.php bestandje in de dir gooien om die standaard file lists te voorkomen, maar da's niet zo'n probleem.

Nog een vraagje, wat is denken jullie handiger? Óf alle bestanden van alle users in 1 dir gooien, óf voor elke user een aparte dir? Ik persoonlijk neig naar de tweede, i.v.m. het overzicht, nadeel is alleen dat ik dan in elke dir ook weer index.php moet zetten, wat bij veel users (momenteel 12000-15000) veel bestanden zijn.

@de mensen die zeggen dat ik het buiten de root moet doen: Heeft iemand misschien een kort code voorbeeldje?

Acties:
  • 0 Henk 'm!

  • doeternietoe
  • Registratie: November 2004
  • Laatst online: 20-09 17:02
Je wilt je bestand afsluiten van de buitenwereld. De eerste stap hierin is om bestanden buiten de webroot te plaatsen. In het geval dat niet mogelijk zou zijn, kun je met htaccess de toegang ook beperken, maar dat is natuurlijk minder flexibel en daarnaast niet altijd 100% waterdicht.

Heb je de bestanden eenmaal afgesloten van de buitenwereld, wil je ze natuurlijk voor een select aantal mensen nog wel beschikbaar houden. De toegang tot je bestanden moet je dan dus via een php-script regelen. Dat php-script moet ook kunnen bepalen of een gebruiker wel of geen toegang heeft en dus niet een dom doorgeefluik zijn. Wat jij wilt is dat Piet waarvan je bepaalt hebt dat hij je bestand moet kunnen downloaden slechts op de link klikt en z'n bestand krijgt. Zet Piet de link echter op een forum, dan moet Henk van datzelfde forum niets met deze link kunnen.

Ik zou dat met de volgende stappen proberen te bereiken:
1) Maak een tabel in de database met daarin: download_id, file_id, download_key. Hierbij is download_key een random string is van afdoende lengte om het raden ervan onmogelijk te maken.
2) Stel vast of een gebruiker toegang moet krijgen tot een file, zo ja, voeg een rij toe in de bovenstaande database in. Creeër met behulp van de download_id en de download_key een link op, bijv: http://www.host.tld/downl...nload_key=38dmnauf8dufhaj
3) In het script waar je download link naar verwijst lees je de download_id en de download_key uit, zoekt op in de database of de combinatie bestaat en zo ja, welke file_id erbij hoort. Met php lees je het bewuste file uit en geef het door aan je gebruiker. Je vernietigd de rij in de database, zodat als henk dezelfde link probeert er geen corresponderende download meer in de database staat.

Verschillende modificaties of verbeteringen zijn op deze methode denkbaar. Zo zou je per rij in de database de tijd kunnen bijhouden en de link na bijv. 5min kunnen laten verlopen.

De download_key lijkt misschien wat overbodig(de link verloopt hoe dan ook) maar voorkomt dat mensen op een drukkere site het systeem gaan saboteren door een zojuist gemaakte link te kopiëren, het id met 1 te verhogen en te plakken in de hoop dat ze degene bij wie dat id werkelijk hoort voor zijn.

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
L0calh0st schreef op donderdag 20 mei 2010 @ 22:05:
[...]

@de mensen die zeggen dat ik het buiten de root moet doen: Heeft iemand misschien een kort code voorbeeldje?
i.p.v.
PHP:
1
readfile('files/'.$hash);

dit?:
PHP:
1
readfile('../files/'.$hash);


En hoe je ergens (buiten de webroot) een mapje aan moet maken weet je zelf denk ik wel ;)

[ Voor 64% gewijzigd door Osiris op 20-05-2010 22:14 ]


Acties:
  • 0 Henk 'm!

  • doeternietoe
  • Registratie: November 2004
  • Laatst online: 20-09 17:02
@Osiris: Ik kan me uiteraard vergissen, maar ik dacht dat fpassthru niet direct een pad accepteerde maar slechts een resource handle aangemaakt met fopen. Voor de rest is het uiteraard de correcte manier om een bestand buiten de webroot door te geven met php.

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Helemaal correct, mea culpa

Maar er is iig zo'n functie die dat wel kan :+ Ik zal eens zoeken :P

edit:
readfile() was het :P

[ Voor 20% gewijzigd door Osiris op 20-05-2010 22:14 ]


Acties:
  • 0 Henk 'm!

  • bindsa
  • Registratie: Juli 2009
  • Niet online
Osiris schreef op donderdag 20 mei 2010 @ 22:10:
[...]

i.p.v.
PHP:
1
readfile('files/'.$hash);

dit?:
PHP:
1
readfile('../files/'.$hash);


En hoe je ergens (buiten de webroot) een mapje aan moet maken weet je zelf denk ik wel ;)
Klinkt als een goed idee. Maar hoe gedraagt dit script zich bijvoorbeeld op een VPS of op een gratis host? En volgens mij is er ook een php.ini instelling die PHP beperkt tot het lezen van bestenden in de webroot (of heb ik dat mis?)

Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Je hebt nu wel genoeg hints om het eerst even zelf te testen. :>

{signature}


Acties:
  • 0 Henk 'm!

  • apokalypse
  • Registratie: Augustus 2004
  • Laatst online: 10:21
L0calh0st schreef op donderdag 20 mei 2010 @ 22:05:
[...]


Hier heb je een punt. Dus als ik in de HTML alleen de file ID laat zien, de namen hash en de downloads met de originele naam aanbiedt (en dit alles dan gekoppeld over de database) moet het redelijk veilig zijn?
Als je vanuit de bestandsnaam de hash gaat berekenen, is het niet helemaal veilig. Ik weet niet hoe PHP zit met het maken van GUID's e.d, ik de comments van http://php.net/manual/en/function.uniqid.php zie ik wel wat staan.

[ Voor 5% gewijzigd door apokalypse op 21-05-2010 17:00 ]


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Een md5 kan je representeren met 32 hex chars, en dat is dus 128 bits. Dat scheelt al heel wat tov 32. ;)

{signature}


Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 19:44
L0calh0st schreef op vrijdag 21 mei 2010 @ 10:37:
[...]

Klinkt als een goed idee. Maar hoe gedraagt dit script zich bijvoorbeeld op een VPS of op een gratis host? En volgens mij is er ook een php.ini instelling die PHP beperkt tot het lezen van bestenden in de webroot (of heb ik dat mis?)
Ik denk dat je de safe mode bedoeld. Deze wordt standaard (vanaf php 5.3.0) niet meer gebruikt (deprecated) dus daar zal je geen last van hebben.
Tevens heeft safe mode geen invloed op het met php-code bereiken van bestanden net buiten jou webroot.

Dus het zal dan ook nog steeds de beste optie zijn.

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

jbdeiman schreef op vrijdag 21 mei 2010 @ 17:11:
Tevens heeft safe mode geen invloed op het met php-code bereiken van bestanden net buiten jou webroot.
Dat is afhankelijk van de instellingen door de webhoster. Wat ik tot nu toe van localhost gehoord heb is hij naar de cheapo hosters aan het kijken, die hebben over het algemeen redelijk stricte security, hebben ze ook minder rotzooi er van.

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 19-09 11:12
Zoals Voutloos al een paar keer heeft gezegd, je doet moeilijk. Begin eens met een folder uit te maken buiten je webroot, daar zet je alle content in wat net gezien mag worden.. Daarna valideer je of de gebruiker het wel mag zien.

Je kan het hele 'wie heeft toegang en wie niet' gewoon laten regelen door PHP met sessies. Hieronder even heel simpel omschreven indien een gebruiker zijn file wil opvragen.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Gebruiker (acties):
    Upload foto:
        Server heeft ontvangen:
            Move naar de directory buiten de webroot, opslaan in je database en afronden maar.
        Server heeft niets ontvangen:
            Foutmelding
    Gebruiker wil foto zien:
        Is de gebruiker ingelogd:
            Heeft de gebruiker toegang:
                Laat zien
            Nee
                Foutmelding
        Nee
            Inlogscherm

Acties:
  • 0 Henk 'm!

  • bindsa
  • Registratie: Juli 2009
  • Niet online
Manuel schreef op vrijdag 21 mei 2010 @ 17:39:
Zoals Voutloos al een paar keer heeft gezegd, je doet moeilijk. Begin eens met een folder uit te maken buiten je webroot, daar zet je alle content in wat net gezien mag worden.. Daarna valideer je of de gebruiker het wel mag zien.

Je kan het hele 'wie heeft toegang en wie niet' gewoon laten regelen door PHP met sessies. Hieronder even heel simpel omschreven indien een gebruiker zijn file wil opvragen.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Gebruiker (acties):
    Upload foto:
        Server heeft ontvangen:
            Move naar de directory buiten de webroot, opslaan in je database en afronden maar.
        Server heeft niets ontvangen:
            Foutmelding
    Gebruiker wil foto zien:
        Is de gebruiker ingelogd:
            Heeft de gebruiker toegang:
                Laat zien
            Nee
                Foutmelding
        Nee
            Inlogscherm
Dat van die folder en dergelijke snap ik allemaal wel, maar net wat Muer zegt, dit werkt niet op alle hosts (i.v.m. beveiliging), en mijn app moet eigenlijk wel op 9/10 hosts kunnen draaien. Dus daarom vroeg ik me af of het toevallig op een andere manier kan, omdat mijn huidige wijze eigenlijk gewoon security through obscurity is, en das niet best ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Gewoon buiten de webroot een map maken en daar alle bestanden in zetten. Met de bestandsnaam zou ik ook niet moeilijk doen met random dingen genereren, maar gewoon de id uit je database als bestandsnaam gebruiken (die is immers al uniek). Dan kun je ook met de database regelen wie toegang tot de bestanden heeft, en weet je zeker dat er niemand anders bij kan ('random'-bestandsnaam raden).

Edit: En waarom zou dat niet op alle hosts werken?
Als je geen map buiten de webroot hebt, dan plaatst je ze in een map binnen de webroot die je met een htaccess ontoegankelijk maakt.

[ Voor 19% gewijzigd door Verwijderd op 21-05-2010 21:43 ]


Acties:
  • 0 Henk 'm!

  • Manuel
  • Registratie: Maart 2008
  • Laatst online: 19-09 11:12
Voor hoeveel gaan we wedden dat dit overal werkt (nooit gratis webhosting gezien, maar goed). Zoals mij heel vaak is gezegd: Meten is weten, kort gezegd, probeer het eerst, zoek dan pas een oplossing. Wat je nu doet is problemen creëren die er niet eens zijn en dat is echt sonde van je tijd.

Dus ga aan de slag zou ik zeggen!

Acties:
  • 0 Henk 'm!

  • MueR
  • Registratie: Januari 2004
  • Laatst online: 14:53

MueR

Admin Tweakers Discord

is niet lief

L0calh0st schreef op vrijdag 21 mei 2010 @ 21:33:
[...]


Dat van die folder en dergelijke snap ik allemaal wel, maar net wat Muer zegt, dit werkt niet op alle hosts (i.v.m. beveiliging), en mijn app moet eigenlijk wel op 9/10 hosts kunnen draaien. Dus daarom vroeg ik me af of het toevallig op een andere manier kan, omdat mijn huidige wijze eigenlijk gewoon security through obscurity is, en das niet best ;)
Nee, je leest niet. Ik reageer op jbdeiman's post die de plank volledig missloeg. Net als jouw aanname dat ik altijd gelijk heb overigens (die is maar voor 99% correct ;)).

Anyone who gets in between me and my morning coffee should be insecure.


Acties:
  • 0 Henk 'm!

  • 448191
  • Registratie: September 2004
  • Laatst online: 06-09-2024
Hoezo moet er rekening gehouden worden met dingen als safe mode? Misschien niet onbelangrijk om even de context te delen.

Als de bestemming namelijk een private server of VPS is, ben je veel beter af met x-sendfile. En als de bestanden groot kunnen zijn, zou ik zeker geen readfile() gebruiken. Dan kan je dus of x-sendfile gebruiken, of, als dat om welke reden dan ook niet kan, kan je in een publieke folder symlinks maken met de sessie ID. Met een custom sessie handler ruim je ze weer op. Dit is niet meer of minder veilig dan sessies.

Acties:
  • 0 Henk 'm!

Verwijderd

(Pseudo)Code met buiten de root:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
$file = $db->fetch('SELECT * FROM files WHERE file_id = ?', $_REQUEST['file_id']);

if ($file) {
  //check permissions to the file

  $filePath = FILES_ROOT .'/'. $file['id'];
  if (file_exists($filePath) {
    $modified = filemtime($filePath);
    header('Content-Type: '. $file['mime_type'];
    header('Content-Disposition: attachment; filename="'. $file['name'] .'.'. $file['extension'] .'"'); //force download dialog
    header('Content-Length: '. filesize($filePath));
    header('Last-Modified: '. @gmdate('D, d M Y H:i:s',$modified) . ' GMT');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); //enable caching
    if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) && @strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $modified) {
        header('HTTP/1.1 304 Not Modified');
        //no need to send the file
    }
    else {
        readfile($filePath);
    }
    exit();
  }
}

header('HTTP/1.1 404 Not Found');
//show some graceful not found message

Acties:
  • 0 Henk 'm!

  • 448191
  • Registratie: September 2004
  • Laatst online: 06-09-2024
Owkay, ik heb dus niet goed gelezen. X-Sendfile is, zoals, ik hierboven al zei, makkelijk te faken met symlinks. Voorbeeld (untested):

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class FakeXSendFile {

    private $_privatePath;

    private $_publicPath;

    private $_gcProb = 100;

    private $_maxLinkLife = 1200;

    public function __construct($privatePath, $publicPath)
    {
        $this->_privatePath = $privatePath;
        $this->_publicPath = $publicPath;
    }
    
    public function createLink($sid, $path)
    {
        if(!is_dir("$publicPath/$sid")){
            mkdir("$publicPath/$sid");
        }

        $linkPath = "$publicPath/$sid/$path";

        symlink("$privatePath/$path", $linkPath);

        return $linkPath;
    }

    public function gc()
    {
        if(0 !== rand(0, $this->getGcProb())){
            return;
        }

        foreach(scandir($publicPath) as $path){

            foreach(scandir($path) as $filename)
            {
                if(filemtime($filename) + $this->getMaxLinkLife() < time()){
                    unlink($filename);
                }
            }

            unlink($path);
        }
    }

    public function getPrivatePath()
    {
        return $this->_privatePath;
    }

    public function setPrivatePath($privatePath)
    {
        $this->_privatePath = $privatePath;
    }

    public function getPublicPath()
    {
        return $this->_publicPath;
    }

    public function setPublicPath($publicPath)
    {
        $this->_publicPath = $publicPath;
    }

    public function getGcProb()
    {
        return $this->_gcProb;
    }

    public function setGcProb($gcProb)
    {
        $this->_gcProb = $_gcProb;
    }

    public function getMaxLinkLife()
    {
        return $this->_maxLinkLife;
    }

    public function setMaxLinkLife($maxLinkLife)
    {
        $this->_maxLinkLife = $maxLinkLife;
    }
}

//...
$handler = new FakeXSendFile($privatePath, $publicPath);

$linkLocation = $handler->createLink(session_id(), $path);

//...
header('Location: ' . $linkLocation);
Pagina: 1