/** * Reads a row of data as an array from a CSV file. It's able to * read memo fields with multiline data. * * @param string $file The filename where to write the data * @param array &$conf The configuration of the dest CSV * * @return mixed Array with the data read or false on error/no more data */ function readQuoted($file, &$conf) { if (!($fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ))) { return false; } $buff = $old = $prev = $c = ''; $ret = array(); $fields = 1; $in_quote = false; $quote = $conf['quote']; $f = (int) $conf['fields']; $sep = $conf['sep']; while (false !== ($ch = fgetc($fp))) { $old = $prev; $prev = $c; $c = $ch; // Common case if ($c != $quote && $c != $sep && $c != "\n" && $c != "\r") { $buff .= $c; continue; } // Start quote. if ($in_quote === false && $quote && $c == $quote && ($prev == $sep || $prev == "\n" || $prev === null || $prev == "\r" || $prev == '' || $prev == ' ' || $prev == '=')) { $in_quote = true; // excel compat, removing the = part but only if we are in a quote if ($prev == '=') { $buff[strlen($buff) - 1] = ''; } } if ($in_quote) { // When does the quote end, make sure it's not double quoted if ($c == $sep && $prev == $quote && $old != $quote) { $in_quote = false; } elseif ($c == $sep && $buff == $quote . $quote) { // In case we are dealing with double quote but empty value $in_quote = false; } elseif ($c == "\n" || $c == "\r") { $sub = $prev == "\r" ? 2 : 1; $buff_len = strlen($buff); if ($buff_len >= $sub && $buff[$buff_len - $sub] == $quote) { $in_quote = false; } } } if (!$in_quote && ($c == $sep || $c == "\n" || $c == "\r")) { $return = File_CSV::_readQuotedFillers($fp, $f, $fields, $ret, $buff, $quote, $c, $sep); if ($return !== false) { return $return; } if ($prev == "\r") { $buff = substr($buff, 0, -1); } // Convert EOL character to Unix EOL (LF). if ($conf['eol2unix']) { $buff = preg_replace('/(\\r\\n|\\r)$/', "\n", $buff); // Below replaces things everywhere not just EOL //$buff = str_replace(array("\r\n", "\r"), "\n", $buff); } $ret[] = File_CSV::unquote($buff, $quote); if (count($ret) === $f) { return $ret; } $buff = ''; ++$fields; continue; } $buff .= $c; } /* If it's the end of the file and we still have something in buffer * then we process it since files can have no CL/FR at the end */ $feof = feof($fp); if ($feof && strlen($buff) > 0 && !in_array($buff, array("\r", "\n"))) { $ret[] = File_CSV::unquote($buff, $quote); if (count($ret) == $f) { return $ret; } } if ($feof && count($ret) !== $f) { $return = File_CSV::_readQuotedFillers($fp, $f, $fields, $ret, $buff, $quote, $c, $sep); if ($return !== false) { return $return; } } return !$feof ? $ret : false; }