示例#1
0
文件: CSV.php 项目: villos/tree_admin
 /**
  * Reads a "row" from a CSV file and return it as an array
  *
  * @param string $file The CSV file
  * @param array  &$conf The configuration of the dest CSV
  *
  * @return mixed Array or false
  */
 function read($file, &$conf)
 {
     static $headers = array();
     if (!($fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ))) {
         return false;
     }
     // The size is limited to 4K
     if (!($line = fgets($fp, 4096))) {
         return false;
     }
     $fields = $conf['fields'] == 1 ? array($line) : explode($conf['sep'], $line);
     $nl = array("\n", "\r", "\r\n");
     if (in_array($fields[count($fields) - 1], $nl)) {
         array_pop($fields);
     }
     $field_count = count($fields);
     $last =& $fields[$field_count - 1];
     $len = strlen($last);
     if ($field_count != $conf['fields'] || $conf['quote'] && ($len !== 0 && $last[$len - 1] == "\n" && ($last[0] == $conf['quote'] && $last[strlen(rtrim($last)) - 1] != $conf['quote'] || $last[0] == '=' && $last[1] == $conf['quote'] || preg_match('|^\\s+' . preg_quote($conf['quote']) . '|Ums', $last, $match)))) {
         fseek($fp, -1 * strlen($line), SEEK_CUR);
         return File_CSV::readQuoted($file, $conf);
     }
     foreach ($fields as $k => $v) {
         $fields[$k] = File_CSV::unquote($v, $conf['quote']);
     }
     if (isset($conf['header']) && empty($headers)) {
         // read the first row and assign to $headers
         $headers = $fields;
         return $headers;
     }
     if ($field_count != $conf['fields']) {
         File_CSV::raiseError("Read wrong fields number count: '" . $field_count . "' expected " . $conf['fields']);
         return true;
     }
     if (!empty($headers)) {
         $tmp = array();
         foreach ($fields as $k => $v) {
             $tmp[$headers[$k]] = $v;
         }
         $fields = $tmp;
     }
     return $fields;
 }
示例#2
0
 /**
  * Reads a "row" from a CSV file and return it as an array
  *
  * @param string $file The CSV file
  * @param array  &$conf The configuration of the dest CSV
  *
  * @return mixed Array or false
  */
 function read($file, &$conf)
 {
     if (!($fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ))) {
         return false;
     }
     // The size is limited to 4K
     if (!($line = fgets($fp, 4096))) {
         return false;
     }
     $fields = explode($conf['sep'], $line);
     if ($conf['quote']) {
         $last =& $fields[count($fields) - 1];
         // Fallback to read the line with readQuoted when guess
         // that the simple explode won't work right
         if ($last[strlen($last) - 1] == "\n" && $last[0] == $conf['quote'] && $last[strlen(rtrim($last)) - 1] != $conf['quote'] || count($fields) != $conf['fields']) {
             $len = strlen($line);
             fseek($fp, -1 * strlen($line), SEEK_CUR);
             return File_CSV::readQuoted($file, $conf);
         } else {
             $last = rtrim($last);
             foreach ($fields as $k => $v) {
                 $fields[$k] = File_CSV::unquote($v, $conf['quote']);
             }
         }
     }
     if (count($fields) != $conf['fields']) {
         File_CSV::raiseError("Read wrong fields number count: '" . count($fields) . "' expected " . $conf['fields']);
         return true;
     }
     return $fields;
 }
示例#3
0
/**
 * The CSV file is parsed here so validation errors can be returned to the
 * user. The data from a successful parsing is stored in the <var>$CVSDATA</var>
 * array so it can be accessed by the submit function
 *
 * @param Pieform  $form   The form to validate
 * @param array    $values The values submitted
 */
function uploadcsv_validate(Pieform $form, $values)
{
    global $CSVDATA, $ALLOWEDKEYS, $FORMAT, $USER;
    // Don't even start attempting to parse if there are previous errors
    if ($form->has_errors()) {
        return;
    }
    if ($values['file']['size'] == 0) {
        $form->set_error('file', $form->i18n('rule', 'required', 'required', array()));
        return;
    }
    require_once 'pear/File.php';
    require_once 'pear/File/CSV.php';
    // Don't be tempted to use 'explode' here. There may be > 1 underscore.
    $break = strpos($values['authinstance'], '_');
    $authinstance = substr($values['authinstance'], 0, $break);
    $institution = substr($values['authinstance'], $break + 1);
    if (!$USER->can_edit_institution($institution)) {
        $form->set_error('authinstance', get_string('notadminforinstitution', 'admin'));
        return;
    }
    $usernames = array();
    $emails = array();
    $conf = File_CSV::discoverFormat($values['file']['tmp_name']);
    $i = 0;
    while ($line = File_CSV::readQuoted($values['file']['tmp_name'], $conf)) {
        $i++;
        if (!is_array($line)) {
            // Note: the CSV parser returns true on some errors and false on
            // others! Yes that's retarded. No I didn't write it :(
            $form->set_error('file', get_string('uploadcsverrorincorrectnumberoffields', 'admin', $i));
            return;
        }
        // Get the format of the file
        if ($i == 1) {
            foreach ($line as &$potentialkey) {
                $potentialkey = trim($potentialkey);
                if (!in_array($potentialkey, $ALLOWEDKEYS)) {
                    $form->set_error('file', get_string('uploadcsverrorinvalidfieldname', 'admin', $potentialkey));
                    return;
                }
            }
            // Now we know all of the field names are valid, we need to make
            // sure that the required fields are included
            $mandatoryfields = array('username', 'password');
            $mandatoryfields = array_merge($mandatoryfields, array_keys(ArtefactTypeProfile::get_mandatory_fields()));
            if ($lockedprofilefields = get_column('institution_locked_profile_field', 'profilefield', 'name', $institution)) {
                $mandatoryfields = array_merge($mandatoryfields, $lockedprofilefields);
            }
            // Add in the locked profile fields for this institution
            foreach ($mandatoryfields as $field) {
                if (!in_array($field, $line)) {
                    $form->set_error('file', get_string('uploadcsverrorrequiredfieldnotspecified', 'admin', $field));
                    return;
                }
            }
            // The format line is valid
            $FORMAT = $line;
            log_info('FORMAT:');
            log_info($FORMAT);
        } else {
            // Trim non-breaking spaces -- they get left in place by File_CSV
            foreach ($line as &$field) {
                $field = preg_replace('/^(\\s|\\xc2\\xa0)*(.*?)(\\s|\\xc2\\xa0)*$/', '$2', $field);
            }
            // We have a line with the correct number of fields, but should validate these fields
            // Note: This validation should really be methods on each profile class, that way
            // it can be used in the profile screen as well.
            $formatkeylookup = array_flip($FORMAT);
            $username = $line[$formatkeylookup['username']];
            $password = $line[$formatkeylookup['password']];
            $email = $line[$formatkeylookup['email']];
            $authobj = AuthFactory::create($authinstance);
            if (method_exists($authobj, 'is_username_valid') && !$authobj->is_username_valid($username)) {
                $form->set_error('file', get_string('uploadcsverrorinvalidusername', 'admin', $i));
                return;
            }
            if (record_exists_select('usr', 'LOWER(username) = ?', strtolower($username)) || isset($usernames[strtolower($username)])) {
                $form->set_error('file', get_string('uploadcsverroruseralreadyexists', 'admin', $i, $username));
                return;
            }
            if (record_exists('usr', 'email', $email) || isset($emails[$email])) {
                $form->set_error('file', get_string('uploadcsverroremailaddresstaken', 'admin', $i, $email));
            }
            // Note: only checks for valid form are done here, none of the checks
            // like whether the password is too easy. The user is going to have to
            // change their password on first login anyway.
            if (method_exists($authobj, 'is_password_valid') && !$authobj->is_password_valid($password)) {
                $form->set_error('file', get_string('uploadcsverrorinvalidpassword', 'admin', $i));
                return;
            }
            $usernames[strtolower($username)] = 1;
            $emails[$email] = 1;
            // All OK!
            $CSVDATA[] = $line;
        }
    }
    if ($i == 1) {
        // There was only the title row :(
        $form->set_error('file', get_string('uploadcsverrornorecords', 'admin'));
        return;
    }
    if ($CSVDATA === null) {
        // Oops! Couldn't get CSV data for some reason
        $form->set_error('file', get_string('uploadcsverrorunspecifiedproblem', 'admin'));
    }
}
示例#4
0
 /**
  * Reads a "row" from a CSV file and return it as an array
  *
  * @param string $file The CSV file
  * @param array  &$conf The configuration of the dest CSV
  *
  * @return mixed Array or false
  */
 function read($file, &$conf)
 {
     if (!($fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ))) {
         return false;
     }
     // The size is limited to 4K
     if (!($line = fgets($fp, 4096))) {
         return false;
     }
     if ($conf['fields'] === 1) {
         $fields = array($line);
         $field_count = 1;
     } else {
         $fields = explode($conf['sep'], $line);
         $field_count = count($fields);
     }
     $real_field_count = $field_count - 1;
     $check_char = $fields[$real_field_count];
     if ($check_char === "\n" || $check_char === "\r") {
         array_pop($fields);
         --$field_count;
     }
     $last =& $fields[$real_field_count];
     if ($field_count !== $conf['fields'] || $conf['quote'] && ($last !== '' && ($last[0] === $conf['quote'] && $last[strlen(rtrim($last)) - 1] !== $conf['quote'] || $last[0] === '=' && $last[1] === $conf['quote'])) || count(explode(',', $line)) > $field_count) {
         fseek($fp, -1 * strlen($line), SEEK_CUR);
         $fields = File_CSV::readQuoted($file, $conf);
         $fields = File_CSV::_processHeaders($fields, $conf);
         return $fields;
     }
     $fields = File_CSV::unquote($fields, $conf['quote']);
     if ($field_count != $conf['fields']) {
         File_CSV::raiseError("Read wrong fields number count: '" . $field_count . "' expected " . $conf['fields']);
         return true;
     }
     $fields = File_CSV::_processHeaders($fields, $conf);
     return $fields;
 }
示例#5
0
 /**
  * Reads a "row" from a CSV file and return it as an array
  *
  * @param string $file The CSV file
  * @param array  &$conf The configuration of the dest CSV
  *
  * @return mixed Array or false
  */
 function read($file, &$conf)
 {
     static $headers = array();
     if (!($fp = File_CSV::getPointer($file, $conf, FILE_MODE_READ))) {
         return false;
     }
     // The size is limited to 4K
     if (!($line = fgets($fp, 4096))) {
         return false;
     }
     if ($conf['fields'] === 1) {
         $fields = array($line);
         $field_count = 1;
     } else {
         $fields = explode($conf['sep'], $line);
         $field_count = count($fields);
         while ($field_count < $conf['fields']) {
             if (!($additional_line = fgets($fp, 4096))) {
                 return false;
             }
             $line .= $additional_line;
             $fields = explode($conf['sep'], $line);
             $field_count = count($fields);
         }
     }
     $real_field_count = $field_count - 1;
     $check_char = $fields[$real_field_count];
     if ($check_char === "\n" || $check_char === "\r") {
         array_pop($fields);
         --$field_count;
     }
     $last =& $fields[$real_field_count];
     if ($field_count !== $conf['fields'] || $conf['quote'] && ($last !== '' && ($last[0] === $conf['quote'] && $last[strlen(rtrim($last)) - 1] !== $conf['quote'] || $last[0] === '=' && $last[1] === $conf['quote'])) || count(explode(',', $line)) > $field_count) {
         fseek($fp, -1 * strlen($line), SEEK_CUR);
         return File_CSV::readQuoted($file, $conf);
     }
     $fields = File_CSV::unquote($fields, $conf['quote']);
     if (isset($conf['header']) && empty($headers)) {
         // read the first row and assign to $headers
         $headers = $fields;
         return $headers;
     }
     if ($field_count != $conf['fields']) {
         File_CSV::raiseError("Read wrong fields number count: '" . $field_count . "' expected " . $conf['fields']);
         return true;
     }
     if (!empty($headers)) {
         $tmp = array();
         foreach ($fields as $k => $v) {
             $tmp[$headers[$k]] = $v;
         }
         $fields = $tmp;
     }
     return $fields;
 }