#!/bin/php -c.. |'); define("INVALID_CHARS_REGEX", '/[:\\x5c\\/*?"<>|]/'); /*. string .*/ function remove_ctrls(/*. string .*/ $s) # Remove CTRLs chars ASCII codes 0-31,127. { return preg_replace("/[\\000-\\037\\177]/", "", $s); } /*. string .*/ function escape_doublequote_backslash(/*. string .*/ $s) { $s = (string) str_replace("\\", "\\\\", $s); $s = (string) str_replace("\"", "\\\"", $s); return $s; } /*. string .*/ function get_extension(/*. string .*/ $fn) /* Returns the extension from the file name $fn. Valid extensions are any sequence of alphanumerical ASCII chars following the last period, ranging from one char up to 4. Returns NULL if no valid extension was found. Examples: "SOMETHING.XyZ" --> "XyZ" "SOME.THING.X" --> "X" "SOMETHING" --> NULL (missing extension) "SOMETHING..." --> NULL (empty extension after last period) "Today 12.08.2006" --> "2006" "photo.album" --> NULL (invalid extension: too long) */ { $i = strrpos($fn, "."); if( $i === FALSE ) return NULL; $ext = substr($fn, (int) $i + 1); if( preg_match("/^[a-zA-Z0-9]{1,4}\$/D", $ext) == 0 ) return NULL; return $ext; } $extensions = array( # See http://www.webmaster-toolkit.com/mime-types.shtml # for a complete list. "application/octet-stream", "bin", "application/octet-stream", "dat", "text/plain", "txt", "text/plain", "text", "text/html", "htm", "text/html", "html", "image/gif", "gif", "image/png", "png", "image/jpeg", "jpg", "image/jpeg", "jpeg", "application/pdf", "pdf", "application/ps", "ps", "video/avi", "avi", ); /*. array[int]string .*/ function extension_to_mimes(/*. string .*/ $ext) { global $extensions; $mime_list = /*.(array[int]string).*/ array(); $n = count($extensions); for($i=0; $i<$n; $i+=2) if( $extensions[$i+1] === $ext ) $mime_list[] = $extensions[$i]; return $mime_list; } /*. array[int]string .*/ function mime_to_extensions(/*. string .*/ $mime) { global $extensions; $ext_list = /*.(array[int]string).*/ array(); $n = count($extensions); for($i=0; $i<$n; $i+=2) if( $extensions[$i] === $mime ) $ext_list[] = $extensions[$i+1]; return $ext_list; } /*. string .*/ function ensure_proper_extension( /*. string .*/ $fn, /*. string .*/ $mime) /* Returns the file name $fn with a proper extension corresponding to the MIME type $mime. If the extension isn't valid or is missing, add one. If the MIME type is unknown, do nothing and returns the filename as is. */ { $exp = mime_to_extensions($mime); if( count($exp) == 0 ) return $fn; $cur = strtolower( get_extension($fn) ); if( in_array($cur, $exp) ) return $fn; return $fn . "." . $exp[0]; } $charsets = array("US-ASCII", "ISO_8859-1", "UTF-8"); class Status { public $file_name = FILE_NAME; /* filename, UTF-8 */ public $charset = 0; /* global $charsets[$this-charset] is the required charset for the filename to be sent via HTTP */ public $filter = TRUE; /* remove special chars */ public $ensure_extension = TRUE; public $encoding = 0; } /*. string .*/ function build_self_url(/*. Status .*/ $s, /*. string .*/ $op) { return $_SERVER["PHP_SELF"] . "?filename=" . rawurlencode($s->file_name) . "&charset=" . $s->charset . ($s->filter? "&filter=1":"") . ($s->ensure_extension? "&ensure_extension=1":"") . "&encoding=" . $s->encoding . "&op=" . $op; } /*. Status .*/ function get_status() { $s = new Status(); if( isset($_REQUEST['filename']) ){ $fn = remove_ctrls( (string) $_REQUEST['filename'] ); $fn = mb_convert_encoding($fn, "UTF-8", "UTF-8"); $s->file_name = $fn; } else { return $s; } if( isset($_REQUEST['charset']) ){ $i = (int) $_REQUEST['charset']; if( $i >= 0 and $i < count($GLOBALS['charsets']) ) $s->charset = $i; } $s->filter = isset( $_REQUEST['filter'] ); $s->ensure_extension = isset( $_REQUEST['ensure_extension'] ); if( isset($_REQUEST['encoding']) ){ $i = (int) $_REQUEST['encoding']; if( $i >= 0 and $i < 4 ) $s->encoding = $i; } return $s; } /*. void .*/ function page_header(/*. string .*/ $title) { header("Content-Type: text/html; charset=UTF-8"); header("Cache-Control: no-cache"); echo "
File Download Test Program
"; } /*. void .*/ function echo_radio( /*. string .*/ $name, /*. int .*/ $value, /*. int .*/ $cur_value, /*. string .*/ $text) { $label = $name . "_" . $value; echo " "; } /*. void .*/ function echo_checkbox( /*. string .*/ $name, /*. int .*/ $value, /*. int .*/ $cur_value, /*. string .*/ $text) { $label = $name . "_" . $value; echo " "; } /*. void .*/ function echo_submit(/*. string .*/ $text, /*. string .*/ $func) { echo ""; } /*. void .*/ function page_menu(/*. Status .*/ $s) { page_header("Configurazione File Download"); echo ""; echo "$agent
" non è riconosciuto da questo
programma. L'impostazione consigliata in questo caso è:
charset ASCII,
codifica raw,
filtro abilitato,
assicura estensione abilitato.
EOT;
}
/*
echo "Il bottone Salva qui sotto in realtà", " non fa nulla, aggiorna solo la pagina. Puoi passare direttamente", " al test più sotto.\n", "
",
"SPAZIO ! \" # \$ % & ' () * + , - . / : ; < = > ? @ [ \\ ] ^ _ ` { | } ~",
"
",
" Il file di test ti verrà inviato con questo nome",
" per verificare se le impostazioni sono adatte al tuo browser."; echo <<< EOT
Problemi? Se non riesci ad ottenere un risultato decente, prova le impostazioni suggerite qui sopra. L'impostazione charset ASCII, filtro attivo, codifica raw dovrebbe funzionare anche con i browser più antiquati. EOT; echo <<< EOT
Sorgente di questo programma. Il sorgente di questo programma di test è scritto nel linguaggio PHP. Il meccanismo per il download del sorgente usa... sè stesso! basta cliccare sull'ancora qui sotto. Hai impostato bene la configurazione? ;-)
EOT; echo "Riferimenti. Per spiegazioni più articolate sul meccanismo di download dei file via WEB, leggi l'articolo PHP File Download (www.icosaedro.it/articoli/php-file-download.html). EOT; page_footer(); } /*. array[int]string .*/ function build_http_headers( /*. Status .*/ $s, /*. string .*/ $filename, /*. string .*/ $mime, /*. string .*/ $path) { $fn = $filename; # Convert filename to the requested charset: $fn_charset = $GLOBALS['charsets'][$s->charset]; $fn = mb_convert_encoding($fn, $fn_charset, FILE_NAME_ENCODING); # Filter invalid characters: if( $s->filter ){ $fn = preg_replace(INVALID_CHARS_REGEX, '_', $fn); } # Ensure proper extension: if( $s->ensure_extension ){ $fn = ensure_proper_extension($fn, $mime); } # Generate filename[*]=... HTTP parameter: switch($s->encoding){ case 0: # Raw encoding: $fn = escape_doublequote_backslash($fn); $fn = "filename=\"$fn\""; break; case 1: # MIME header encoding (RFC 2047): $fn = "filename=\"=?$fn_charset?B?" . base64_encode($fn) . "?=\""; # FIXME: RFC 2047 states that there is a 75 chars length limit; # no problems with 100+ on Mozilla. break; case 2: # Enhanced encoding (RFC 2231): $fn = "filename*=$fn_charset''" . rawurlencode($fn); break; case 3: $fn = "filename=" . rawurlencode($fn); break; default: exit("unexpected encoding " . $s->encoding); } $a[0] = "Content-Type: $mime"; $a[1] = "Content-Disposition: attachment" #. "; size=" . filesize($path) # <-- FIXME: not supported (2183) . "; " . $fn; $a[2] = "Content-Length: " . filesize($path); $a[3] = "Cache-Control: no-cache"; # FIXME return $a; } /*. string .*/ function string_to_literal(/*. string .*/ $s) { return '"' . addcslashes($s, "\000..\037\"\${\177..\377") . '"'; } /*. void .*/ function page_download(/*. Status .*/ $s) { page_header("Configurazione - Download del File di Test"); echo "
Il file di test è un documento PDF di circa 5 KB.
"; $a = build_http_headers($s, $s->file_name, FILE_TYPE, FILE_PATH); echo "Header HTTP che verrà usato:";
foreach($a as $v)
echo "header(" . htmlspecialchars( string_to_literal($v) ), ");
\n";
echo "
";
echo "SCARICA IL FILE DI TEST",
htmlspecialchars( $s->file_name ), ")
",
" RIPROVA CON NUOVI PARAMETRI
",
" Se il risultato non è soddisfacente, prova con altri parametri.",
" La maschera per la configurazione riporta in fondo",
" le impostazioni suggerite in base al browser che stai usando.";
page_footer();
}
/*. void .*/ function download_file(
/*. Status .*/ $s,
/*. string .*/ $file_name,
/*. string .*/ $file_type,
/*. string .*/ $file_path)
{
$a = build_http_headers($s, $file_name, $file_type, $file_path);
foreach($a as $v)
header($v);
readfile($file_path);
}
#
# MAIN
#
# Sets the char that substitute those that cannot be converted toward
# the intended charset:
mb_substitute_character(ord("_"));
# Restore info from sticky form:
$s = get_status();
#
# Request handler:
#
if( $_SERVER['REQUEST_METHOD'] === "GET" && isset($_GET['op']) ){
$op = (string) $_GET['op'];
} else if( $_SERVER['REQUEST_METHOD'] === "POST" ){
$op = NULL;
foreach( /*. (array[string]string) .*/ $_POST as $k => $v ){
if( substr($k, 0, 7) === "button_" ){
$op = substr($k, 7);
break;
}
}
if( $op === NULL ){
trigger_error("missing button_* in POST");
$op = "page_menu";
}
} else {
$op = "page_menu";
}
switch($op){
case "page_menu": page_menu($s); break;
case "page_save": page_menu($s); break;
case "page_download": page_download($s); break;
case "download_file":
download_file($s, $s->file_name, FILE_TYPE, FILE_PATH);
break;
case "download_source":
$fn = basename( $_SERVER["SCRIPT_FILENAME"] );
$s->file_name = $fn;
download_file($s, $fn, "text/plain", $fn);
break;
default: page_menu($s); break;
}
?>