Documentation TYPO3 par Ameos

export.php

00001 <?php
00002 /* $Id: export.php,v 2.27.2.1 2005/09/14 17:06:22 lem9 Exp $ */
00003 // vim: expandtab sw=4 ts=4 sts=4:
00004 
00008 require_once('./libraries/grab_globals.lib.php');
00009 require_once('./libraries/common.lib.php');
00010 require_once('./libraries/zip.lib.php');
00011 
00012 PMA_checkParameters(array('what'));
00013 
00014 // What type of export are we doing?
00015 if ($what == 'excel') {
00016     $type = 'csv';
00017 } else {
00018     $type = $what;
00019 }
00020 
00021 // Get the functions specific to the export type
00022 require('./libraries/export/' . PMA_securePath($type) . '.php');
00023 
00024 // Generate error url
00025 if ($export_type == 'server') {
00026     $err_url = 'server_export.php?' . PMA_generate_common_url();
00027 } elseif ($export_type == 'database') {
00028     $err_url = 'db_details_export.php?' . PMA_generate_common_url($db);
00029 } else {
00030     $err_url = 'tbl_properties_export.php?' . PMA_generate_common_url($db, $table);
00031 }
00032 
00036 @set_time_limit($cfg['ExecTimeLimit']);
00037 
00038 // Start with empty buffer
00039 $dump_buffer = '';
00040 $dump_buffer_len = 0;
00041 
00042 // We send fake headers to avoid browser timeout when buffering
00043 $time_start = time();
00044 
00045 
00054 function PMA_exportOutputHandler($line)
00055 {
00056     global $time_start, $dump_buffer, $dump_buffer_len, $save_filename;
00057 
00058     // Kanji encoding convert feature
00059     if ($GLOBALS['output_kanji_conversion']) {
00060         $line = PMA_kanji_str_conv($line, $GLOBALS['knjenc'], isset($GLOBALS['xkana']) ? $GLOBALS['xkana'] : '');
00061     }
00062     // If we have to buffer data, we will perform everything at once at the end
00063     if ($GLOBALS['buffer_needed']) {
00064 
00065         $dump_buffer .= $line;
00066         if ($GLOBALS['onfly_compression']) {
00067 
00068             $dump_buffer_len += strlen($line);
00069 
00070             if ($dump_buffer_len > $GLOBALS['memory_limit']) {
00071                 if ($GLOBALS['output_charset_conversion']) {
00072                     $dump_buffer = PMA_convert_string($GLOBALS['charset'], $GLOBALS['charset_of_file'], $dump_buffer);
00073                 }
00074                 // as bzipped
00075                 if ($GLOBALS['compression'] == 'bzip'  && @function_exists('bzcompress')) {
00076                     $dump_buffer = bzcompress($dump_buffer);
00077                 }
00078                 // as a gzipped file
00079                 else if ($GLOBALS['compression'] == 'gzip' && @function_exists('gzencode')) {
00080                     // without the optional parameter level because it bug
00081                     $dump_buffer = gzencode($dump_buffer);
00082                 }
00083                 if ($GLOBALS['save_on_server']) {
00084                     $write_result = @fwrite($GLOBALS['file_handle'], $dump_buffer);
00085                     if (!$write_result || ($write_result != strlen($dump_buffer))) {
00086                         $GLOBALS['message'] = sprintf($GLOBALS['strNoSpace'], htmlspecialchars($save_filename));
00087                         $GLOBALS['show_error_header'] = TRUE;
00088                         return FALSE;
00089                     }
00090                 } else {
00091                     echo $dump_buffer;
00092                 }
00093                 $dump_buffer = '';
00094                 $dump_buffer_len = 0;
00095             }
00096         } else {
00097             $time_now = time();
00098             if ($time_start >= $time_now + 30) {
00099                 $time_start = $time_now;
00100                 header('X-pmaPing: Pong');
00101             } // end if
00102         }
00103     } else {
00104         if ($GLOBALS['asfile']) {
00105             if ($GLOBALS['save_on_server'] && strlen($line) > 0) {
00106                 $write_result = @fwrite($GLOBALS['file_handle'], $line);
00107                 if (!$write_result || ($write_result != strlen($line))) {
00108                     $GLOBALS['message'] = sprintf($GLOBALS['strNoSpace'], htmlspecialchars($save_filename));
00109                     $GLOBALS['show_error_header'] = TRUE;
00110                     return FALSE;
00111                 }
00112                 $time_now = time();
00113                 if ($time_start >= $time_now + 30) {
00114                     $time_start = $time_now;
00115                     header('X-pmaPing: Pong');
00116                 } // end if
00117             } else {
00118                 // We export as file - output normally
00119                 if ($GLOBALS['output_charset_conversion']) {
00120                     $line = PMA_convert_string($GLOBALS['charset'], $GLOBALS['charset_of_file'], $line);
00121                 }
00122                 echo $line;
00123             }
00124         } else {
00125             // We export as html - replace special chars
00126             echo htmlspecialchars($line);
00127         }
00128     }
00129     return TRUE;
00130 } // end of the 'PMA_exportOutputHandler()' function
00131 
00132 // Will we save dump on server?
00133 $save_on_server = isset($cfg['SaveDir']) && !empty($cfg['SaveDir']) && !empty($onserver);
00134 
00135 // Ensure compressed formats are associated with the download feature
00136 if (empty($asfile)) {
00137     if ($save_on_server) {
00138         $asfile = TRUE;
00139     } elseif (isset($compression) && ($compression == 'zip' | $compression == 'gzip' | $compression == 'bzip')) {
00140         $asfile = TRUE;
00141     } else {
00142         $asfile = FALSE;
00143     }
00144 } else {
00145     $asfile = TRUE;
00146 }
00147 
00148 // Defines the default <CR><LF> format. For SQL always use \n as MySQL wants this on all platforms.
00149 if ($what == 'sql') {
00150     $crlf = "\n";
00151 } else {
00152     $crlf = PMA_whichCrlf();
00153 }
00154 
00155 $output_kanji_conversion = function_exists('PMA_kanji_str_conv') && $type != 'xls';
00156 
00157 // Do we need to convert charset?
00158 $output_charset_conversion = $asfile &&
00159     $cfg['AllowAnywhereRecoding'] && $allow_recoding
00160     && isset($charset_of_file) && $charset_of_file != $charset
00161     && $type != 'xls';
00162 
00163 // Set whether we will need buffering
00164 $buffer_needed = isset($compression) && ($compression == 'zip' | $compression == 'gzip' | $compression == 'bzip');
00165 
00166 // Use on fly compression?
00167 $onfly_compression = $GLOBALS['cfg']['CompressOnFly'] && isset($compression) && ($compression == 'gzip' | $compression == 'bzip');
00168 if ($onfly_compression) {
00169     $memory_limit = trim(@ini_get('memory_limit'));
00170     // 2 MB as default
00171     if (empty($memory_limit)) $memory_limit = 2 * 1024 * 1024;
00172 
00173     if (strtolower(substr($memory_limit, -1)) == 'm') $memory_limit = (int)substr($memory_limit, 0, -1) * 1024 * 1024;
00174     elseif (strtolower(substr($memory_limit, -1)) == 'k') $memory_limit = (int)substr($memory_limit, 0, -1) * 1024;
00175     elseif (strtolower(substr($memory_limit, -1)) == 'g') $memory_limit = (int)substr($memory_limit, 0, -1) * 1024 * 1024 * 1024;
00176     else $memory_limit = (int)$memory_limit;
00177 
00178     // Some of memory is needed for other thins and as treshold.
00179     // Nijel: During export I had allocated (see memory_get_usage function)
00180     //        approx 1.2MB so this comes from that.
00181     if ($memory_limit > 1500000) $memory_limit -= 1500000;
00182 
00183     // Some memory is needed for compression, assume 1/3
00184     $memory_limit *= 2/3;
00185 }
00186 
00187 // Generate filename and mime type if needed
00188 if ($asfile) {
00189     $pma_uri_parts = parse_url($cfg['PmaAbsoluteUri']);
00190     if ($export_type == 'server') {
00191         if (isset($remember_template)) {
00192             setcookie('pma_server_filename_template', $filename_template , 0, $GLOBALS['cookie_path'], '' , $GLOBALS['is_https']);
00193         }
00194         $filename = str_replace('__SERVER__', $GLOBALS['cfg']['Server']['host'], strftime($filename_template));
00195     } elseif ($export_type == 'database') {
00196         if (isset($remember_template)) {
00197             setcookie('pma_db_filename_template', $filename_template , 0, $GLOBALS['cookie_path'], '' , $GLOBALS['is_https']);
00198         }
00199         $filename = str_replace('__DB__', $db, str_replace('__SERVER__', $GLOBALS['cfg']['Server']['host'], strftime($filename_template)));
00200     } else {
00201         if (isset($remember_template)) {
00202             setcookie('pma_table_filename_template', $filename_template , 0, $GLOBALS['cookie_path'], '' , $GLOBALS['is_https']);
00203         }
00204         $filename = str_replace('__TABLE__', $table, str_replace('__DB__', $db, str_replace('__SERVER__', $GLOBALS['cfg']['Server']['host'], strftime($filename_template))));
00205     }
00206 
00207     // convert filename to iso-8859-1, it is safer
00208     if (!(isset($cfg['AllowAnywhereRecoding']) && $cfg['AllowAnywhereRecoding'] && $allow_recoding)) {
00209         $filename = PMA_convert_string($charset, 'iso-8859-1', $filename);
00210     } else {
00211         $filename = PMA_convert_string($convcharset, 'iso-8859-1', $filename);
00212     }
00213 
00214     // Generate basic dump extension
00215     if ($type == 'csv') {
00216         $filename  .= '.csv';
00217         $mime_type = 'text/comma-separated-values';
00218     } else if ($type == 'htmlexcel') {
00219         $filename  .= '.xls';
00220         $mime_type = 'application/vnd.ms-excel';
00221     } else if ($type == 'htmlword') {
00222         $filename  .= '.doc';
00223         $mime_type = 'application/vnd.ms-word';
00224     } else if ($type == 'xls') {
00225         $filename  .= '.xls';
00226         $mime_type = 'application/vnd.ms-excel';
00227     } else if ($type == 'xml') {
00228         $filename  .= '.xml';
00229         $mime_type = 'text/xml';
00230     } else if ($type == 'latex') {
00231         $filename  .= '.tex';
00232         $mime_type = 'application/x-tex';
00233     } else {
00234         $filename  .= '.sql';
00235         // text/x-sql is correct MIME type, however safari ignores further
00236         // Content-Disposition header, so we must force it to download it this
00237         // way...
00238         $mime_type = PMA_USR_BROWSER_AGENT == 'SAFARI'
00239                         ? 'application/octet-stream'
00240                         : 'text/x-sql';
00241     }
00242 
00243     // If dump is going to be compressed, set correct encoding or mime_type and add
00244     // compression to extension
00245     $content_encoding = '';
00246     if (isset($compression) && $compression == 'bzip') {
00247         $filename  .= '.bz2';
00248         // browsers don't like this:
00249         //$content_encoding = 'x-bzip2';
00250         $mime_type = 'application/x-bzip2';
00251     } else if (isset($compression) && $compression == 'gzip') {
00252         $filename  .= '.gz';
00253         // Needed to avoid recompression by server modules like mod_gzip.
00254         // It seems necessary to check about zlib.output_compression
00255         // to avoid compressing twice
00256         if (!@ini_get('zlib.output_compression')) {
00257             $content_encoding = 'x-gzip';
00258             $mime_type = 'application/x-gzip';
00259         }
00260     } else if (isset($compression) && $compression == 'zip') {
00261         $filename  .= '.zip';
00262         $mime_type = 'application/zip';
00263     }
00264 }
00265 
00266 // Open file on server if needed
00267 if ($save_on_server) {
00268     if (substr($cfg['SaveDir'], -1) != '/') {
00269         $cfg['SaveDir'] .= '/';
00270     }
00271     $save_filename = $cfg['SaveDir'] . preg_replace('@[/\\\\]@','_',$filename);
00272     unset($message);
00273     if (file_exists($save_filename) && empty($onserverover)) {
00274         $message = sprintf($strFileAlreadyExists, htmlspecialchars($save_filename));
00275         $GLOBALS['show_error_header'] = TRUE;
00276     } else {
00277         if (is_file($save_filename) && !is_writable($save_filename)) {
00278             $message = sprintf($strNoPermission, htmlspecialchars($save_filename));
00279             $GLOBALS['show_error_header'] = TRUE;
00280         } else {
00281             if (!$file_handle = @fopen($save_filename, 'w')) {
00282                 $message = sprintf($strNoPermission, htmlspecialchars($save_filename));
00283                 $GLOBALS['show_error_header'] = TRUE;
00284             }
00285         }
00286     }
00287     if (isset($message)) {
00288         $js_to_run = 'functions.js';
00289         require_once('./header.inc.php');
00290         if ($export_type == 'server') {
00291             $active_page = 'server_export.php';
00292             require('./server_export.php');
00293         } elseif ($export_type == 'database') {
00294             $active_page = 'db_details_export.php';
00295             require('./db_details_export.php');
00296         } else {
00297             $active_page = 'tbl_properties_export.php';
00298             require('./tbl_properties_export.php');
00299         }
00300         exit();
00301     }
00302 }
00303 
00308 if (!$save_on_server) {
00309     if ($asfile ) {
00310         // Download
00311         if (!empty($content_encoding)) {
00312             header('Content-Encoding: ' . $content_encoding);
00313         }
00314         header('Content-Type: ' . $mime_type);
00315         header('Expires: ' . gmdate('D, d M Y H:i:s') . ' GMT');
00316         // lem9: Tested behavior of 
00317         //       IE 5.50.4807.2300
00318         //       IE 6.0.2800.1106 (small glitch, asks twice when I click Open) 
00319         //       IE 6.0.2900.2180
00320         //       Firefox 1.0.6
00321         // in http and https
00322         header('Content-Disposition: attachment; filename="' . $filename . '"');
00323         if (PMA_USR_BROWSER_AGENT == 'IE') {
00324             header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
00325             header('Pragma: public');
00326         } else {
00327             header('Pragma: no-cache');
00328         }
00329     } else {
00330         // HTML
00331         $backup_cfgServer = $cfg['Server'];
00332         require_once('./header.inc.php');
00333         $cfg['Server'] = $backup_cfgServer;
00334         unset($backup_cfgServer);
00335         echo "\n" . '<div align="' . $cell_align_left . '">' . "\n";
00336         //echo '    <pre>' . "\n";
00337         echo '    <form name="nofunction">' . "\n"
00338            // remove auto-select for now: there is no way to select
00339            // only a part of the text; anyway, it should obey
00340            // $cfg['TextareaAutoSelect']
00341            //. '        <textarea name="sqldump" cols="50" rows="30" onclick="this.select();" id="textSQLDUMP" wrap="OFF">' . "\n";
00342            . '        <textarea name="sqldump" cols="50" rows="30" id="textSQLDUMP" wrap="OFF">' . "\n";
00343     } // end download
00344 }
00345 
00346 // Check if we have something to export
00347 if ($export_type == 'database') {
00348     $tables     = PMA_DBI_get_tables($db);
00349     $num_tables = count($tables);
00350     if ($num_tables == 0) {
00351         $message = $strNoTablesFound;
00352         $js_to_run = 'functions.js';
00353         require_once('./header.inc.php');
00354         if ($export_type == 'server') {
00355             $active_page = 'server_export.php';
00356             require('./server_export.php');
00357         } elseif ($export_type == 'database') {
00358             $active_page = 'db_details_export.php';
00359             require('./db_details_export.php');
00360         } else {
00361             $active_page = 'tbl_properties_export.php';
00362             require('./tbl_properties_export.php');
00363         }
00364         exit();
00365     }
00366 }
00367 
00368 // Fake loop just to allow skip of remain of this code by break, I'd really
00369 // need exceptions here :-)
00370 do {
00371 
00372 // Add possibly some comments to export
00373 if (!PMA_exportHeader()) break;
00374 
00375 // Will we need relation & co. setup?
00376 $do_relation = isset($GLOBALS[$what . '_relation']);
00377 $do_comments = isset($GLOBALS[$what . '_comments']);
00378 $do_mime     = isset($GLOBALS[$what . '_mime']);
00379 if ($do_relation || $do_comments || $do_mime) {
00380     require_once('./libraries/relation.lib.php');
00381     $cfgRelation = PMA_getRelationsParam();
00382 }
00383 if ($do_mime) {
00384     require_once('./libraries/transformations.lib.php');
00385 }
00386 
00387 // Include dates in export?
00388 $do_dates   = isset($GLOBALS[$what . '_dates']);
00389 
00393 // Gets the number of tables if a dump of a database has been required
00394 if ($export_type == 'server') {
00398     if ($server > 0 && empty($dblist)) {
00399         PMA_availableDatabases();
00400     }
00401 
00402     if (isset($db_select)) {
00403         $tmp_select = implode($db_select, '|');
00404         $tmp_select = '|' . $tmp_select . '|';
00405     }
00406     // Walk over databases
00407     foreach ($dblist AS $current_db) {
00408         if ((isset($tmp_select) && strpos(' ' . $tmp_select, '|' . $current_db . '|'))
00409             || !isset($tmp_select)) {
00410             if (!PMA_exportDBHeader($current_db))
00411                 break 2;
00412             if (!PMA_exportDBCreate($current_db))
00413                 break 2;
00414             $tables = PMA_DBI_get_tables($current_db);
00415             foreach ($tables as $table) {
00416                 $local_query  = 'SELECT * FROM ' . PMA_backquote($current_db) . '.' . PMA_backquote($table);
00417                 if (isset($GLOBALS[$what . '_structure'])) {
00418                     if (!PMA_exportStructure($current_db, $table, $crlf, $err_url, $do_relation, $do_comments, $do_mime, $do_dates))
00419                         break 3;
00420                 }
00421                 if (isset($GLOBALS[$what . '_data'])) {
00422                     if (!PMA_exportData($current_db, $table, $crlf, $err_url, $local_query))
00423                         break 3;
00424                 }
00425             }
00426             if (!PMA_exportDBFooter($current_db))
00427                 break 2;
00428         }
00429     }
00430 } elseif ($export_type == 'database') {
00431     if (!PMA_exportDBHeader($db))
00432         break;
00433 
00434     if (isset($table_select)) {
00435         $tmp_select = implode($table_select, '|');
00436         $tmp_select = '|' . $tmp_select . '|';
00437     }
00438     $i = 0;
00439     foreach ($tables as $table) {
00440         $local_query  = 'SELECT * FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table);
00441         if ((isset($tmp_select) && strpos(' ' . $tmp_select, '|' . $table . '|'))
00442             || !isset($tmp_select)) {
00443 
00444             if (isset($GLOBALS[$what . '_structure'])) {
00445                 if (!PMA_exportStructure($db, $table, $crlf, $err_url, $do_relation, $do_comments, $do_mime, $do_dates))
00446                     break 2;
00447             }
00448             if (isset($GLOBALS[$what . '_data'])) {
00449                 if (!PMA_exportData($db, $table, $crlf, $err_url, $local_query))
00450                     break 2;
00451             }
00452         }
00453     }
00454     if (!PMA_exportDBFooter($db))
00455         break;
00456 } else {
00457     if (!PMA_exportDBHeader($db))
00458         break;
00459     // We export just one table
00460 
00461     if ($limit_to > 0 && $limit_from >= 0) {
00462         $add_query  = ' LIMIT '
00463                     . (($limit_from > 0) ? $limit_from . ', ' : '')
00464                     . $limit_to;
00465     } else {
00466         $add_query  = '';
00467     }
00468 
00469     if (!empty($sql_query)) {
00470         $local_query = $sql_query . $add_query;
00471         PMA_DBI_select_db($db);
00472     } else {
00473         $local_query  = 'SELECT * FROM ' . PMA_backquote($db) . '.' . PMA_backquote($table) . $add_query;
00474     }
00475 
00476     if (isset($GLOBALS[$what . '_structure'])) {
00477         if (!PMA_exportStructure($db, $table, $crlf, $err_url, $do_relation, $do_comments, $do_mime, $do_dates))
00478             break;
00479     }
00480     if (isset($GLOBALS[$what . '_data'])) {
00481         if (!PMA_exportData($db, $table, $crlf, $err_url, $local_query))
00482             break;
00483     }
00484     if (!PMA_exportDBFooter($db))
00485         break;
00486 }
00487 if (!PMA_exportFooter()) break;
00488 
00489 } while (FALSE);
00490 // End of fake loop
00491 
00492 if ($save_on_server && isset($message)) {
00493     $js_to_run = 'functions.js';
00494     require_once('./header.inc.php');
00495     if ($export_type == 'server') {
00496         $active_page = 'server_export.php';
00497         require('./server_export.php');
00498     } elseif ($export_type == 'database') {
00499         $active_page = 'db_details_export.php';
00500         require('./db_details_export.php');
00501     } else {
00502         $active_page = 'tbl_properties_export.php';
00503         require('./tbl_properties_export.php');
00504     }
00505     exit();
00506 }
00507 
00511 if (!empty($asfile)) {
00512     // Convert the charset if required.
00513     if ($output_charset_conversion) {
00514         $dump_buffer = PMA_convert_string($GLOBALS['charset'], $GLOBALS['charset_of_file'], $dump_buffer);
00515     }
00516 
00517     // Do the compression
00518     // 1. as a gzipped file
00519     if (isset($compression) && $compression == 'zip') {
00520         if (@function_exists('gzcompress')) {
00521             $zipfile = new zipfile();
00522             $zipfile -> addFile($dump_buffer, substr($filename, 0, -4));
00523             $dump_buffer = $zipfile -> file();
00524         }
00525     }
00526     // 2. as a bzipped file
00527     else if (isset($compression) && $compression == 'bzip') {
00528         if (@function_exists('bzcompress')) {
00529             $dump_buffer = bzcompress($dump_buffer);
00530             if ($dump_buffer === -8) {
00531                 require_once('./header.inc.php');
00532                 echo sprintf($strBzError, '<a href="http://bugs.php.net/bug.php?id=17300" target="_blank">17300</a>');
00533                 require_once('./footer.inc.php');
00534             }
00535         }
00536     }
00537     // 3. as a gzipped file
00538     else if (isset($compression) && $compression == 'gzip') {
00539         if (@function_exists('gzencode')) {
00540             // without the optional parameter level because it bug
00541             $dump_buffer = gzencode($dump_buffer);
00542         }
00543     }
00544 
00545     /* If ve saved on server, we have to close file now */
00546     if ($save_on_server) {
00547         $write_result = @fwrite($file_handle, $dump_buffer);
00548         fclose($file_handle);
00549         if (strlen($dump_buffer) !=0 && (!$write_result || ($write_result != strlen($dump_buffer)))) {
00550             $message = sprintf($strNoSpace, htmlspecialchars($save_filename));
00551         } else {
00552             $message = sprintf($strDumpSaved, htmlspecialchars($save_filename));
00553         }
00554 
00555         $js_to_run = 'functions.js';
00556         require_once('./header.inc.php');
00557         if ($export_type == 'server') {
00558             $active_page = 'server_export.php';
00559             require_once('./server_export.php');
00560         } elseif ($export_type == 'database') {
00561             $active_page = 'db_details_export.php';
00562             require_once('./db_details_export.php');
00563         } else {
00564             $active_page = 'tbl_properties_export.php';
00565             require_once('./tbl_properties_export.php');
00566         }
00567         exit();
00568     } else {
00569         echo $dump_buffer;
00570     }
00571 }
00575 else {
00579     //echo '    </pre>' . "\n";
00580     echo '</textarea>' . "\n"
00581        . '    </form>' . "\n";
00582     echo '</div>' . "\n";
00583     echo "\n";
00584 ?><script language="JavaScript" type="text/javascript">
00585 <!--
00586     var bodyWidth=null; var bodyHeight=null;
00587     if (document.getElementById('textSQLDUMP')) {
00588         bodyWidth  = self.innerWidth;
00589         bodyHeight = self.innerHeight;
00590         if(!bodyWidth && !bodyHeight){
00591             if (document.compatMode && document.compatMode == "BackCompat") {
00592                 bodyWidth  = document.body.clientWidth;
00593                 bodyHeight = document.body.clientHeight;
00594             } else if (document.compatMode && document.compatMode == "CSS1Compat") {
00595                 bodyWidth  = document.documentElement.clientWidth;
00596                 bodyHeight = document.documentElement.clientHeight;
00597             }
00598         }
00599         document.getElementById('textSQLDUMP').style.width=(bodyWidth-50) + 'px';
00600         document.getElementById('textSQLDUMP').style.height=(bodyHeight-100) + 'px';
00601     }
00602 //-->
00603 </script>
00604 <?php
00605     require_once('./footer.inc.php');
00606 } // end if
00607 ?>


Généré par Les experts TYPO3 avec  doxygen 1.4.6