home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / phpMyAdmin / libraries / import / csv.php next >
Encoding:
PHP Script  |  2008-06-23  |  10.1 KB  |  324 lines

  1. <?php
  2. /* vim: set expandtab sw=4 ts=4 sts=4: */
  3. /**
  4.  * CSV import plugin for phpMyAdmin
  5.  *
  6.  * @todo    add an option for handling NULL values
  7.  * @version $Id: csv.php 11326 2008-06-17 21:32:48Z lem9 $
  8.  */
  9. if (! defined('PHPMYADMIN')) {
  10.     exit;
  11. }
  12.  
  13. /**
  14.  *
  15.  */
  16. if ($plugin_param !== 'table') {
  17.     return;
  18. }
  19.  
  20. if (isset($plugin_list)) {
  21.     $plugin_list['csv'] = array(
  22.         'text' => 'strCSV',
  23.         'extension' => 'csv',
  24.         'options' => array(
  25.             array('type' => 'bool', 'name' => 'replace', 'text' => 'strReplaceTable'),
  26.             array('type' => 'bool', 'name' => 'ignore', 'text' => 'strIgnoreDuplicates'),
  27.             array('type' => 'text', 'name' => 'terminated', 'text' => 'strFieldsTerminatedBy', 'size' => 2, 'len' => 2),
  28.             array('type' => 'text', 'name' => 'enclosed', 'text' => 'strFieldsEnclosedBy', 'size' => 2, 'len' => 2),
  29.             array('type' => 'text', 'name' => 'escaped', 'text' => 'strFieldsEscapedBy', 'size' => 2, 'len' => 2),
  30.             array('type' => 'text', 'name' => 'new_line', 'text' => 'strLinesTerminatedBy', 'size' => 2),
  31.             array('type' => 'text', 'name' => 'columns', 'text' => 'strColumnNames'),
  32.             ),
  33.         'options_text' => 'strOptions',
  34.         );
  35.     /* We do not define function when plugin is just queried for information above */
  36.     return;
  37. }
  38.  
  39. $replacements = array(
  40.     '\\n'   => "\n",
  41.     '\\t'   => "\t",
  42.     '\\r'   => "\r",
  43.     );
  44. $csv_terminated = strtr($csv_terminated, $replacements);
  45. $csv_enclosed = strtr($csv_enclosed,  $replacements);
  46. $csv_escaped = strtr($csv_escaped, $replacements);
  47. $csv_new_line = strtr($csv_new_line, $replacements);
  48.  
  49. if (strlen($csv_terminated) != 1) {
  50.     $message = sprintf($strInvalidCSVParameter, $strFieldsTerminatedBy);
  51.     $show_error_header = TRUE;
  52.     $error = TRUE;
  53.     // The default dialog of MS Excel when generating a CSV produces a 
  54.     // semi-colon-separated file with no chance of specifying the 
  55.     // enclosing character. Thus, users who want to import this file 
  56.     // tend to remove the enclosing character on the Import dialog. 
  57.     // I could not find a test case where having no enclosing characters 
  58.     // confuses this script.
  59.     // But the parser won't work correctly with strings so we allow just
  60.     // one character.
  61. } elseif (strlen($csv_enclosed) > 1) {
  62.     $message = sprintf($strInvalidCSVParameter, $strFieldsEnclosedBy);
  63.     $show_error_header = TRUE;
  64.     $error = TRUE;
  65. } elseif (strlen($csv_escaped) != 1) {
  66.     $message = sprintf($strInvalidCSVParameter, $strFieldsEscapedBy);
  67.     $show_error_header = TRUE;
  68.     $error = TRUE;
  69. } elseif (strlen($csv_new_line) != 1 && $csv_new_line != 'auto') {
  70.     $message = sprintf($strInvalidCSVParameter, $strLinesTerminatedBy);
  71.     $show_error_header = TRUE;
  72.     $error = TRUE;
  73. }
  74.  
  75. $buffer = '';
  76. if (isset($csv_replace)) {
  77.     $sql_template = 'REPLACE';
  78. } else {
  79.     $sql_template = 'INSERT';
  80.     if (isset($csv_ignore)) {
  81.         $sql_template .= ' IGNORE';
  82.     }
  83. }
  84. $sql_template .= ' INTO ' . PMA_backquote($table);
  85.  
  86. $tmp_fields = PMA_DBI_get_fields($db, $table);
  87.  
  88. if (empty($csv_columns)) {
  89.     $fields = $tmp_fields;
  90. } else {
  91.     $sql_template .= ' (';
  92.     $fields = array();
  93.     $tmp   = split(',( ?)', $csv_columns);
  94.     foreach ($tmp as $key => $val) {
  95.         if (count($fields) > 0) {
  96.             $sql_template .= ', ';
  97.         }
  98.         $val = trim($val);
  99.         $found = FALSE;
  100.         foreach ($tmp_fields as $id => $field) {
  101.             if ($field['Field'] == $val) {
  102.                 $found = TRUE;
  103.                 break;
  104.             }
  105.         }
  106.         if (!$found) {
  107.             $message = sprintf($strInvalidColumn, $val);
  108.             $show_error_header = TRUE;
  109.             $error = TRUE;
  110.             break;
  111.         }
  112.         $fields[] = $field;
  113.         $sql_template .= PMA_backquote($val);
  114.     }
  115.     $sql_template .= ') ';
  116. }
  117.  
  118. $required_fields = count($fields);
  119.  
  120. $sql_template .= ' VALUES (';
  121.  
  122. // Defaults for parser
  123. $i = 0;
  124. $len = 0;
  125. $line = 1;
  126. $lasti = -1;
  127. $values = array();
  128. $csv_finish = FALSE;
  129.  
  130. while (!($finished && $i >= $len) && !$error && !$timeout_passed) {
  131.     $data = PMA_importGetNextChunk();
  132.     if ($data === FALSE) {
  133.         // subtract data we didn't handle yet and stop processing
  134.         $offset -= strlen($buffer);
  135.         break;
  136.     } elseif ($data === TRUE) {
  137.         // Handle rest of buffer
  138.     } else {
  139.         // Append new data to buffer
  140.         $buffer .= $data;
  141.         unset($data);
  142.         // Do not parse string when we're not at the end and don't have new line inside
  143.         if (($csv_new_line == 'auto' && strpos($buffer, "\r") === FALSE && strpos($buffer, "\n") === FALSE)
  144.             || ($csv_new_line != 'auto' && strpos($buffer, $csv_new_line) === FALSE)) {
  145.             continue;
  146.         }
  147.     }
  148.  
  149.     // Current length of our buffer
  150.     $len = strlen($buffer);
  151.     // Currently parsed char
  152.     $ch = $buffer[$i];
  153.     while ($i < $len) {
  154.         // Deadlock protection
  155.         if ($lasti == $i && $lastlen == $len) {
  156.             $message = sprintf($strInvalidCSVFormat, $line);
  157.             $show_error_header = TRUE;
  158.             $error = TRUE;
  159.             break;
  160.         }
  161.         $lasti = $i;
  162.         $lastlen = $len;
  163.  
  164.         // This can happen with auto EOL and \r at the end of buffer
  165.         if (!$csv_finish) {
  166.             // Grab empty field
  167.             if ($ch == $csv_terminated) {
  168.                 if ($i == $len - 1) {
  169.                     break;
  170.                 }
  171.                 $values[] = '';
  172.                 $i++;
  173.                 $ch = $buffer[$i];
  174.                 continue;
  175.             }
  176.  
  177.             // Grab one field
  178.             $fallbacki = $i;
  179.             if ($ch == $csv_enclosed) {
  180.                 if ($i == $len - 1) {
  181.                     break;
  182.                 }
  183.                 $need_end = TRUE;
  184.                 $i++;
  185.                 $ch = $buffer[$i];
  186.             } else {
  187.                 $need_end = FALSE;
  188.             }
  189.             $fail = FALSE;
  190.             $value = '';
  191.             while (($need_end && $ch != $csv_enclosed)
  192.              || (!$need_end && !($ch == $csv_terminated
  193.                || $ch == $csv_new_line || ($csv_new_line == 'auto'
  194.                 && ($ch == "\r" || $ch == "\n"))))) {
  195.                 if ($ch == $csv_escaped) {
  196.                     if ($i == $len - 1) {
  197.                         $fail = TRUE;
  198.                         break;
  199.                     }
  200.                     $i++;
  201.                     $ch = $buffer[$i];
  202.                 }
  203.                 $value .= $ch;
  204.                 if ($i == $len - 1) {
  205.                     if (!$finished) {
  206.                         $fail = TRUE;
  207.                     }
  208.                     break;
  209.                 }
  210.                 $i++;
  211.                 $ch = $buffer[$i];
  212.             }
  213.  
  214.             // unquoted NULL string
  215.             if (false === $need_end && $value === 'NULL') {
  216.                 $value = null;
  217.             }
  218.  
  219.             if ($fail) {
  220.                 $i = $fallbacki;
  221.                 $ch = $buffer[$i];
  222.                 break;
  223.             }
  224.             // Need to strip trailing enclosing char?
  225.             if ($need_end && $ch == $csv_enclosed) {
  226.                 if ($finished && $i == $len - 1) {
  227.                     $ch = NULL;
  228.                 } elseif ($i == $len - 1) {
  229.                     $i = $fallbacki;
  230.                     $ch = $buffer[$i];
  231.                     break;
  232.                 } else {
  233.                     $i++;
  234.                     $ch = $buffer[$i];
  235.                 }
  236.             }
  237.             // Are we at the end?
  238.             if ($ch == $csv_new_line || ($csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n")) || ($finished && $i == $len - 1)) {
  239.                 $csv_finish = TRUE;
  240.             }
  241.             // Go to next char
  242.             if ($ch == $csv_terminated) {
  243.                 if ($i == $len - 1) {
  244.                     $i = $fallbacki;
  245.                     $ch = $buffer[$i];
  246.                     break;
  247.                 }
  248.                 $i++;
  249.                 $ch = $buffer[$i];
  250.             }
  251.             // If everything went okay, store value
  252.             $values[] = $value;
  253.         }
  254.  
  255.         // End of line
  256.         if ($csv_finish || $ch == $csv_new_line || ($csv_new_line == 'auto' && ($ch == "\r" || $ch == "\n"))) {
  257.             if ($csv_new_line == 'auto' && $ch == "\r") { // Handle "\r\n"
  258.                 if ($i >= ($len - 2) && !$finished) {
  259.                     break; // We need more data to decide new line
  260.                 }
  261.                 if ($buffer[$i + 1] == "\n") {
  262.                     $i++;
  263.                 }
  264.             }
  265.             // We didn't parse value till the end of line, so there was empty one
  266.             if (!$csv_finish) {
  267.                 $values[] = '';
  268.             }
  269.             // Do we have correct count of values?
  270.             if (count($values) != $required_fields) {
  271.  
  272.                 // Hack for excel
  273.                 if ($values[count($values) - 1] == ';') {
  274.                     unset($values[count($values) - 1]);
  275.                 } else {
  276.                     $message = sprintf($strInvalidCSVFieldCount, $line);
  277.                     $show_error_header = TRUE;
  278.                     $error = TRUE;
  279.                     break;
  280.                 }
  281.             }
  282.  
  283.             $first = TRUE;
  284.             $sql = $sql_template;
  285.             foreach ($values as $key => $val) {
  286.                 if (!$first) {
  287.                     $sql .= ', ';
  288.                 }
  289.                 if ($val === null) {
  290.                     $sql .= 'NULL';
  291.                 } else {
  292.                     $sql .= '\'' . addslashes($val) . '\'';
  293.                 }
  294.  
  295.                 $first = FALSE;
  296.             }
  297.             $sql .= ')';
  298.  
  299.             /**
  300.              * @todo maybe we could add original line to verbose SQL in comment
  301.              */
  302.             PMA_importRunQuery($sql, $sql);
  303.             $line++;
  304.             $csv_finish = FALSE;
  305.             $values = array();
  306.             $buffer = substr($buffer, $i + 1);
  307.             $len = strlen($buffer);
  308.             $i = 0;
  309.             $lasti = -1;
  310.             $ch = $buffer[0];
  311.         }
  312.     } // End of parser loop
  313. } // End of import loop
  314.  
  315. // Commit any possible data in buffers
  316. PMA_importRunQuery();
  317.  
  318. if (count($values) != 0 && !$error) {
  319.     $message = sprintf($strInvalidCSVFormat, $line);
  320.     $show_error_header = TRUE;
  321.     $error = TRUE;
  322. }
  323. ?>
  324.