Come creare un’area download sfruttando il Directory Listing

WordPress è un fantastico CMS – Anzi, non ho più dubbi: è il miglior CMS! Ma – ahimé – nemmeno WordPress è perfetto e la sua imperfezione, a mio parere, deriva dal suo immenso database di plugin che spesso, purtroppo, sono obsoleti o scritti letteralmente coi piedi, o solo di facciata per spingerti a passare ad una versione a pagamento 😐

Questo, se da una parte porta ad una vastità smodata di possibilità, dall’altra porta anche ad avere a che fare con prodotti terribilmente vecchi, buggati, che piazzano il loro codice per l’intero blog anche se – esempio – dovrebbero lavorare solo nel backend, o solo su una specifica pagina, ecc ecc…

A causa di ciò, faccio quanto in mio potere per evitare plugin minori, con poche o scarse recensioni, dove l’autore non risponde mai (plugin abbandonati o quasi).

Per fare ciò, quando possibile, mi faccio dei plugin per conto mio e sfrutto delle funzioni di wordpress nel mio custom-function.php

Codice mio, testato e verificato, fa solo quello che dico io e come lo voglio io. No more, no less 😛

 

Dopo questa dovuta premessa, ecco che arrivo al punto: “L’Area Download”!

Ho provato tutti i plugin presenti sul database wordpress, ma ce ne fosse stato uno che mi sia piaciuto davvero 🙁

L’ultimo testato era: wp-downloadmanager

Old style, alcuni bug, ma – nonostante ciò – decisamente migliore di tanti altri.

 

In ogni caso, non pienamente soddisfatto, ho provato a fare da me.

In un primo momento pensavo di sfruttare un mio vecchio script:
SimpleFileList > Download + Demo

Ma avrei dovuto migliorarlo per renderlo ricorsivo, dargli un po’ di colore ecc… così ho preferito lavorare su una soluzione diversa che mi permettesse, tra l’altro, di scriverci su un articoletto interessante.

Ecco dunque che ho realizzato un’area download senza index, sfruttando mod_autoindex, insomma, e l’ho abbellita niente male con una serie di regole che adesso vi racconterò 🙂

La guida richiede una discreta conoscenza dell’.htaccess, che il sito sia ospitato su hosting con server apache, e che sia abilitato il modulo mod_autoindex (directory listing).

Possiamo iniziare verificando il tutto creando via ftp una directory di lavoro (eg: _download) e quindi creiamo un .htaccess dentro questa directory (e, magari, anche qualche directory o qualche file di esempio).

Apriamo il nuovo .htaccess appena creato, e aggiungiamo questa riga per verificare che tutto funzioni: Options +Indexes

Fatto ciò, andando su: http://nostrosito.**/_download, dovremmo ritrovarci una struttura simile (diversamente … o abbiam sbagliato qualcosa, o mod_autoindex è disabilitato dall’hosting e lì posso fare ben poco per aiutarvi: chiedete assistenza a loro e incrociate le dita):

Lo so, avete perfettamente ragione!

Graficamente è penosa come lista!

Ma vi garantisco che siamo solo all’inizio 😀

 

 

Proviamo a migliorare le cose aggiungendo IndexOptions FancyIndexing al nostro htaccess.

Ricarichiamo la pagina, e adesso dovremmo ritrovarci qualcosa del genere (il che è già un po’ meglio):

E se volessimo aggiungere delle icone?

Una descrizione?

Cambiare l’ordine di default?

Inserire un css?

Magari aggiungere un po’ di javascript per fare alcuni fix al sorgente (eg: cambiare il titolo)?

 

Tutto possibilissimo, e anche relativamente semplice, grazie alla documentazione su apache.org:mod_autoindex

No, ok, spiegarvi ogni singola riga dell’htaccess potrebbe diventare noioso!

Io lo pubblico per intero, ed ha i suoi commenti.

Le singole funzioni – per i desiderosi di sapere – sono ben descritte nella pagina della documentazione apache precedentemente linkata 😉


Il mio attuale codice!

 

/_download/.htaccess

# No fileindex
DirectoryIndex none.none

## Enable Indexing
Options +Indexes

## deny hotlink by referer
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?miosito.xx [NC]
RewriteCond %{REQUEST_URI} !^/_download/_struttura/ [NC]
RewriteRule ^(.*)$ "https://www.miosito.xx/download/#(goto):$1" [L,R,NE]
</IfModule>

# Security and force download!
<Files *.*>
Options -ExecCGI
Header set Content-Disposition attachment
RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo
</Files>

# fix issue with url files :P
<Files *.url>
ForceType application/octet-stream
</Files>

# Set options
IndexOptions FancyIndexing HTMLTable FoldersFirst iconsAreLinks Charset=UTF-8 XHTML DescriptionWidth=50 NameWidth=50
IndexOrderDefault Descending Date

# Css + Header + Footer
IndexHeadInsert "<script type='text/javascript' src='/_download/_struttura/js/global.js'></script>"
IndexStyleSheet /_download/_struttura/css/style.css
HeaderName /_download/_struttura/html/header.html
ReadmeName /_download/_struttura/html/footer.html

# ExcludeList
IndexIgnore _struttura

# Set icon
DefaultIcon /_download/_struttura/icons/help.png
AddIcon (parent,/_download/_struttura/icons/house_go2.png) ..
AddIcon (tick,/_download/_struttura/icons/tick.png) ^^BLANKICON^^
AddIcon (folder,/_download/_struttura/icons/folder.png) ^^DIRECTORY^^
AddIcon (url,/_download/_struttura/icons/world_link.png) .url
AddIcon (music,/_download/_struttura/icons/music.png) .mp3
AddIcon (txt,/_download/_struttura/icons/text_signature.png) .txt
AddIcon (pdf,/_download/_struttura/icons/page_white_word.png) .doc .docx
AddIcon (pdf,/_download/_struttura/icons/page_white_acrobat.png) .pdf
AddIcon (odt,/_download/_struttura/icons/text_signature.png) .odt
AddIcon (css,/_download/_struttura/icons/css.png) .css
AddIcon (php,/_download/_struttura/icons/page_white_php.png) .php .php3 .php4 .php5 
AddIcon (html,/_download/_struttura/icons/html.png) .htm .html
AddIcon (images,/_download/_struttura/icons/photos.png) .jpg .jpeg .png .gif .bmp
AddIcon (archive,/_download/_struttura/icons/compress.png) .zip .rar .gzip .tar
AddIcon (terminal,/_download/_struttura/icons/application_view_list.png) .exe .msi
AddIcon (terminal,/_download/_struttura/icons/application_xp_terminal.png) .exe .bat .cmd

##### descr max 50 bytes!!! #####
AddDescription "[Top^]" ..

# Folder descriptions (+quotes if has spaces)!
AddDescription "doc, xls, pdf, txt, ecc" Documenti
AddDescription "Php/Html Script" "Script & CMS"
AddDescription "ecv template+istruzioni" "Europass CV - IT"
AddDescription "Programmi e Utility" Software
AddDescription "Router Firmware/Utility" "Firmware & Modding"

# File descriptions
AddDescription "File batch" .bat .cmd
AddDescription "Mp3 File" .mp3
AddDescription "GZIP TAR archive" .tgz .tar.gz
AddDescription "GZIP archive" .Z .z .gz .zip
AddDescription "RAR archive" .rar
AddDescription "TAR archive" .tar
AddDescription "ZIP archive" .zip 
AddDescription "Executable Win. Files" .exe
AddDescription "Windows Installer" .msi
AddDescription "CGI Script" .cgi
AddDescription "Jpeg Image" .jpg .jpeg .jpe
AddDescription "Gif Image" .gif
AddDescription "Png Image" .png
AddDescription "Vector graphic" .ps .ai .eps
AddDescription "Html file" .html .shtml .htm
AddDescription "Css file" .css
AddDescription "DocType Definition" .dtd
AddDescription "Xml file" .xml
AddDescription "Compressed HTML help" .chm
AddDescription "Pdf File" .pdf
AddDescription "Plain text file" .txt .nfo .faq .readme
AddDescription "Unix man page" .man
AddDescription "Email data" .eml .mbox
AddDescription "MS Word document" .doc .docx
AddDescription "OpenDocument" .odt
AddDescription "PHP Script" .php  .php3 .php4
AddDescription "PHP source code" .phps
AddDescription "Javascript" .js
AddDescription "Java code" .java
AddDescription "Unix shell script" .sh .shar .csh .ksh .command
AddDescription "Mac OS X shell script" .command
AddDescription "Configuration file" .conf
AddDescription "Mac OS X terminal" .term
AddDescription "BitTorrent file" .torrent
AddDescription "Windows link" .lnk .url

# Default description
AddDescription "[unknown item..]" *

 

/_download/_struttura/css/style.css

#h1indexlist {
    font: 2em Georgia, serif
}
#indexlist {
    font: .9em/1.3em "Courier New", Courier;
    border-spacing: 0;
    color: #777
}
#indexlist img {
    margin: 3px 0
}
#indexlist a:link,
#indexlist a:visited {
    text-decoration: none
}
#indexlist a:link {
    color: #555
}
#indexlist a:visited {
    color: #777
}
#indexlist a:active,
#indexlist a:hover {
    text-decoration: underline;
    color: #007acc
}
#indexlist tr {
    line-height: 35px
}
#indexlist td {
    padding: 5px;
}
#indexlist th {
    padding: 0 5px;
}
#indexlist tr.even {
    background-color: #F7F7F7
}
#indexlist tr.odd {
    background-color: #DAE6F5
}
#indexlist .indexcolicon {
    text-align: left
}
#indexlist .indexcolname {
    width: 35%;
    text-align: left
}
#indexlist .indexcollastmod,
#indexlist .indexcolsize {
    text-align: center
}
#indexlist .indexcoldesc {
    width: 25%;
    text-align: right
}
#indexlist .indexcollastmod {
    width: 25%
}
#indexlist .indexcolsize {
    width: 15%
}
#indexfooterurl {
    line-height: 30px;
}
#indexfooterurl a {
    color: #007acc
}

 

/_download/_struttura/html/header.html

<h1 id="h1indexlist"></h1><!-- used via innerHTML -->

 

/_download/_struttura/html/footer.html

<div id="indexfooterurl"></div><!-- used via innerHTML -->
<script type='text/javascript' src='/_download/_struttura/js/iframeResizer.contentWindow.min.js'></script>
<!-- source: https://raw.githubusercontent.com/davidjbradshaw/iframe-resizer/master/js/iframeResizer.contentWindow.min.js -->

 

/_download/_struttura/js/global.js

//////////

// Config:
var _new_title = 'Root';
var _dir_path = '_download';
var _iframe_uri = 'download';
var _root_title = 'Index of /' + _dir_path + '';
var _iframe_page_title = 'Download - L’AltroWeb'; // iframe title page

// set fixedtitle var
var _fixedtitle = document.title

// set wlh var
var _wlh = window.location.href;
_wlh = _wlh.replace(_dir_path + '/', _iframe_uri + '/');

// set hash:
var _hash = _wlh.replace(_iframe_uri + '/', _iframe_uri + '/#(goto):');

//////////


// allow only inside iframe!
if (self == top)
{
    if (document.title == _root_title)
    {
        window.location.href = _wlh; //redirect
    }
    else
    {
        _wlh = _hash;    
        window.location.href = _wlh; //redirect
    }
}
else
{
    if (document.title == _root_title)
    {
        // add css if is root directory:
        document.write('<style type="text/css">tbody tr.even:nth-child(3){display:none}</style>');
    }
    else
    {
        // else add hash:
        _wlh = _hash;    
    }
    // then >  update url:
    if (top.document.title == _iframe_page_title)
    {
        top.history.pushState(null, null, _wlh);    
    }
}


// innerHTML:
window.onload = function()
{
    _fixedtitle = _fixedtitle.replace(_root_title, _new_title);
    _fixedtitle = _fixedtitle.replace(/\//g, ' &gt; ');
    document.getElementById("h1indexlist").innerHTML = _fixedtitle;
    document.getElementById("indexfooterurl").innerHTML = 'url: <a href="' + _wlh +'" title="Link diretto" target="_top">' + decodeURIComponent(_wlh) +'</a>';
}

 

Pagina Download

<script type="text/javascript">
// accept anchor as link
var _wlh = window.location.hash;
if (_wlh.match(/\#\(goto\)\:/g)) // > eg: fix tag tag-more!
{
    _wlh = _wlh.replace('#(goto):', '');
}
else
{
    _wlh = '';
}
document.write('<iframe src="/_download/' + _wlh + '" frameborder="0" scrolling="no" style="width:100%;border:0"></iframe>');
</script>
<!-- source: //raw.githubusercontent.com/davidjbradshaw/iframe-resizer/master/js/iframeResizer.min.js -->
<script type="text/javascript" src="/_download/_struttura/js/iframeResizer.min.js"></script>
<script type="text/javascript">iFrameResize()</script>
<noscript>
    <p>download area: <a href="/_download/" title="noscript release">https://www.miosito.xx/_download/</a></p>
</noscript>

 

Icone:

http://www.famfamfam.com/lab/icons/silk/


Come si può notare è dunque un iframe corretto via javascript (ci ho dovuto lavorare un po’, ma adesso – a mio parere – funiona benissimo e mi piace davvero molto così)!

Risultato ftp:
Come possiamo notare abbiamo l’htaccess nella root;

le varie directory che formeranno le categorie della nostra area download;

la directory “_struttura” (nascosta dall’area download grazie a IndexIgnore _struttura)

nessun file index.php o html (se li mettessimo sarebbero semplicemente presenti in lista e disponibili al download grazie a DirectoryIndex none.none) 😉

 

Risultato browser:

Beh, direi che il miglioramento è davvero niente male, non trovate? 🙂

Questi i miei colori e il mio personale gusto. A voi basterà modificare il file .css per meglio adattarlo alle vostre esigenze.

Bene, spero sia tutto abbastanza chiaro e il codice sufficiente per permettere anche a voi, voi che usate wordpress, drupal, joomla, o un semplice sito in html (ma sempre su server apache), di creare – a vostro piacimento – la vostra area download.


Volete migliorarvi con WordPress? Qui alcuni titoli interessanti:

[amazon_link asins=’8850333234,8820363585,8820372916,8820374773,8820378205,8850332033,B00Y06B37E,B01MZ63P01,8848129668′ template=’ProductCarousel’ store=’lal0a-21′ marketplace=’IT’ link_id=’a45b2d00-d466-11e6-a175-e37475b2e297′]


Per ogni domanda o dubbio, ovviamente, non esitate a chiedere 😉


PS: trovate l’intera struttura direttamente in un archivio zip, nella stessa area download: ./Script & CMS/_download_htaccess-script.zip




8 commenti su “Come creare un’area download sfruttando il Directory Listing”

  1. Did it! I download “iframeResizer.contentWindow.min.js” and “iframeResizer.min.js” too. Now I’m working on modifying titles, paths, CSS. How can I change the files paths to another location?
    Another question is about the security aspects. is this script safe enough to use it in a production server?

    Rispondi
    • iframeResizer.min.js is and iframeResizer.contentWindow.min.js are already in archive 😉

      u can rename directory and modify htaccess with a good editor
      search: “_download”
      replace “new_name”

      same in javascript and in html files (with notepad++ u can search and replace in *files with one click).

      please, stay attention to not generate conflict with others url (eg: wp-slug)
      for this i’ve used an underscore with a very simple/little name.

      security: upload is from ftp (by admin).
      not upload private data and no security issue can exist.
      php, cgi etc are disabled by htaccess! then, no problem with this.

      # Security and force download!
      Options -ExecCGI
      Header set Content-Disposition attachment
      RemoveHandler .cgi .php .php3 .php4 .php5 .phtml .pl .py .pyc .pyo

      Rispondi
  2. Now it is working. I really thank you for your help 🙂 . There are some few questions. when I am in root folder I still have “.. parent folder”. It should detect that there is no parent folder an I think you have done it by defining “var _iframe_page_title =” with “title of page” + ” – ” + title of your blog in global.js and activate “display=none” in a condition. But mine doesn’t work.

    next, where should I add “direction:rtl;” to change the files table direction?

    Rispondi
  3. I think the problem is using the script on localhost (xampp) in detecting correct iframe and document URI. It doesn’t add “localhost” in URI. I am looking for the place that I have to add “‘localhost/’+” or something like that. I’m sure that it will work on an online server.
    Thanks Salvatore for your useful script.

    Rispondi

Lascia un commento

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.