', '
'); - } + // overwrite default error delimiters + $this->set_error_delimiters('', '
'); + } - /** - * Checks if a username or email is unique. - * - * @param string $value - * @param string $params - */ - function unique($value, $params) { - $CI =& get_instance(); + /** + * Sets rules. + * + * @see CI_Form_validation::set_rules() + */ + public function set_rules($field, $label = '', $rules = '') { + // this will prevent the form_validation from working + if (count($_POST) === 0 && count($_FILES) > 0) { + // add a dummy $_POST + $_POST['DUMMY_ITEM'] = ''; + parent::set_rules($field, $label, $rules); + unset($_POST['DUMMY_ITEM']); + } else { + // we are safe just run as is + parent::set_rules($field, $label, $rules); + } + } - $CI->form_validation->set_message('unique', 'The %s is already being used.'); + /** + * Runs the validator. + * + * @see CI_Form_validation::run() + */ + public function run($group = '') { + $rc = false; + log_message('debug', "Called MY_Form_validation::run()"); - list($table, $field) = explode(".", $params, 2); + // does it have a file only form? + if (count($_POST) === 0 && count($_FILES) > 0) { + // add a dummy $_POST + $_POST['DUMMY_ITEM'] = ''; + $rc = parent::run($group); + unset($_POST['DUMMY_ITEM']); + } else { + // we are safe just run as is + $rc = parent::run($group); + } - $query = $CI->db->select($field)->from($table)->where($field, $value)->limit(1)->get(); + return $rc; + } - if ($query->row()) { - return false; - } else { - return true; - } - } + /** + * Executes the validation routines. + * + * @see CI_Form_validation::_execute() + */ + function _execute($row, $rules, $postdata = null, $cycles = 0) { + log_message('debug', "Called MY_Form_validation::_execute() " . $row['field']); + + if (isset($_FILES[$row['field']])) { + // it is a file so process as a file + log_message('debug', "Processing as a file"); + $postdata = $_FILES[$row['field']]; + + // before doing anything check for errors + if ($postdata['error'] !== UPLOAD_ERR_OK && $postdata['error'] !== UPLOAD_ERR_NO_FILE) { + $this->_error_array[$row['field']] = $this->getUploadError($postdata['error']); + return false; + } + + $_in_array = false; + + // if the field is blank, but NOT required, no further tests are necessary + $callback = false; + if (!in_array('file_required', $rules) && $postdata['error'] === UPLOAD_ERR_NO_FILE) { + // before we bail out, does the rule contain a callback? + if (preg_match("/(callback_\w+)/", implode(' ', $rules), $match)) { + $callback = true; + $rules = array('1' => $match[1]); + } else { + return; + } + } + + // partly copied from the original class + foreach ($rules as $rule) { + // is the rule a callback? + $callback = false; + if (substr($rule, 0, 9) == 'callback_') { + $rule = substr($rule, 9); + $callback = true; + } + + // rules can contain a parameter: max_length[5] + $param = false; + if (preg_match("/(.*?)\[(.*?)\]/", $rule, $match)) { + $rule = $match[1]; + $param = $match[2]; + } + + // call the function that corresponds to the rule + if ($callback === true) { + if (!method_exists($this->CI, $rule)) { + continue; + } + + // run the function and grab the result + $result = $this->CI->$rule($postdata, $param); + + // re-assign the result to the master data array + if ($_in_array == true) { + $this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result; + } else { + $this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result; + } + + // if the field isn't required and we just processed a callback we'll move on... + if (!in_array('file_required', $rules, true) && $result !== false) { + return; + } + } else { + if (!method_exists($this, $rule)) { + /* + * If our own wrapper function doesn't exist we see if a native + * PHP function does. Users can use any native PHP function call + * that has one param. + */ + if (function_exists($rule)) { + $result = $rule($postdata); + + if ($_in_array == true) { + $this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result; + } else { + $this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result; + } + } + + continue; + } + + $result = $this->$rule($postdata, $param); + + if ($_in_array == true) { + $this->_field_data[$row['field']]['postdata'][$cycles] = (is_bool($result)) ? $postdata : $result; + } else { + $this->_field_data[$row['field']]['postdata'] = (is_bool($result)) ? $postdata : $result; + } + } + + // TODO The following line needs testing!!! Not sure if it will work + + // put back the tested values back into $_FILES + //$_FILES[$row['field']] = $this->_field_data[$row['field']]['postdata']; + + // did the rule test negatively? If so, grab the error. + if ($result === false) { + if (!isset($this->_error_messages[$rule])) { + if (false === ($line = $this->CI->lang->line($rule))) { + $line = 'Unable to access an error message corresponding to your field name.'; + } + } else { + $line = $this->_error_messages[$rule]; + } + + /* + * Is the parameter we are inserting into the error message the name + * of another field? If so we need to grab it's "field label". + */ + if (isset($this->_field_data[$param]) && isset($this->_field_data[$param]['label'])) { + $param = $this->_field_data[$param]['label']; + } + + // build the error message + $message = sprintf($line, $this->_translate_fieldname($row['label']), $param); + + // save the error message + $this->_field_data[$row['field']]['error'] = $message; + + if (!isset($this->_error_array[$row['field']])) { + $this->_error_array[$row['field']] = $message; + } + + return; + } + } + } else { + log_message('debug', "Called parent::_execute()"); + parent::_execute($row, $rules, $postdata,$cycles); + } + } + + /** + * Checks if a username or email is unique. + * + * @param string $value + * @param string $params + */ + public function unique($value, $params) { + $CI =& get_instance(); + + $this->set_message('unique', _('The %s is already being used.')); + + list($table, $field) = explode(".", $params, 2); + + $query = $CI->db->select($field)->from($table)->where($field, $value)->limit(1)->get(); + + if ($query->row()) { + return false; + } else { + return true; + } + } + + /** + * Returns the upload error as a human-readable string. + * + * @param integer $errorCode + * @return string + */ + private function getUploadError($errorCode) { + switch ($errorCode) { + case UPLOAD_ERR_INI_SIZE: + $error = $this->setError('upload_file_exceeds_limit'); + break; + case UPLOAD_ERR_FORM_SIZE: + $error = $this->setError('upload_file_exceeds_form_limit'); + break; + case UPLOAD_ERR_PARTIAL: + $error = $this->setError('upload_file_partial'); + break; + case UPLOAD_ERR_NO_FILE: + $error = $this->setError('upload_no_file_selected'); + break; + case UPLOAD_ERR_NO_TMP_DIR: + $error = $this->setError('upload_no_temp_directory'); + break; + case UPLOAD_ERR_CANT_WRITE: + $error = $this->setError('upload_unable_to_write_file'); + break; + case UPLOAD_ERR_EXTENSION: + $error = $this->setError('upload_stopped_by_extension'); + break; + default: + $error = _('Unknown upload error'); + } + + return $error; + } + + /** + * Returns the error message of choice. + * + * The function will use $msg if it cannot find the error in the language file. + * + * @param string $msg the error message + */ + private function setError($msg) { + $CI =& get_instance(); + $CI->lang->load('upload'); + + $msg = ($CI->lang->line($msg) == false) ? $msg : $CI->lang->line($msg); + log_message('error', $msg); + + return $msg; + } + + /** + * Converts a given string in format of ###AA to the number of bits it is assigning. + * + * @see http://codeigniter.com/forums/viewthread/123816/P20 + * + * @param string $sValue + * @return integer number of bits + */ + private function letToBit($sValue) { + // split value from name + if (!preg_match('/([0-9]+)([ptgmkb]{1,2}|)/ui', $sValue, $aMatches)) { + // invalid input + return false; + } + + if (empty($aMatches[2])) { + // no name? Enter default value + $aMatches[2] = 'KB'; + } + + if (strlen($aMatches[2]) == 1) { + // shorted name? Full name + $aMatches[2] .= 'B'; + } + + $iBit = (substr($aMatches[2], -1) == 'B') ? 1024 : 1000; + // calculate bits + switch (strtoupper(substr($aMatches[2], 0, 1))) { + case 'P': + $aMatches[1] *= $iBit; + case 'T': + $aMatches[1] *= $iBit; + case 'G': + $aMatches[1] *= $iBit; + case 'M': + $aMatches[1] *= $iBit; + case 'K': + $aMatches[1] *= $iBit; + break; + } + + // return the value in bits + return $aMatches[1]; + } + + /** + * Checks if a required file is uploaded. + * + * @param mixed $file + */ + public function file_required($file) { + if ($file['size'] === 0) { + $this->set_message('file_required', _('Uploading a file for %s is required.')); + return false; + } + return true; + } + + /** + * Checks if a file is within expected file size limit. + * + * @param mixed $file + * @param mixed $maxSize + */ + public function file_size_max($file, $maxSize) { + if ($file['size'] > $this->letToBit($maxSize)) { + $this->set_message('file_size_max', sprintf(_('The selected file is too big. (Maximum allowed is %s)', $maxSize))); + return false; + } + return true; + } + + /** + * Checks if a file is bigger than minimum size. + * + * @param mixed $file + * @param mixed $minSize + */ + public function file_size_min($file, $minSize) { + if ($file['size'] < $this->letToBit($minSize)) { + $this->set_message('file_size_min', sprintf(_('The selected file is too small. (Minimum allowed is %s)'), $minSize)); + return false; + } + return true; + } + + /** + * Checks the file extension for valid file types. + * + * @param mixed $file + * @param mixed $type + */ + public function file_allowed_type($file, $type) { + // is type of format a,b,c,d? -> convert to array + $exts = explode(',', $type); + + // is $type array? run self recursively + if (count($exts) > 1) { + foreach ($exts as $v) { + $rc = $this->file_allowed_type($file,$v); + if ($rc === true) { + return true; + } + } + } + + // is type a group type? image, application, code... -> load proper array + $extGroups = array(); + $extGroups['image'] = array('jpg', 'jpeg', 'gif', 'png'); + $extGroups['config'] = array('calc', 'par'); + $extGroups['application'] = array('exe', 'dll', 'so', 'cgi'); + $extGroups['php_code'] = array('php', 'php4', 'php5', 'inc', 'phtml'); + $extGroups['compressed'] = array('zip', 'gzip', 'tar', 'gz'); + + if (array_key_exists($exts[0], $extGroups)) { + $exts = $extGroups[$exts[0]]; + } + + // get file ext + $file_ext = strrchr($file['name'], '.'); + $file_ext = substr(strtolower($file_ext), 1); + + if (!in_array($file_ext, $exts)) { + $this->set_message('file_allowed_type', sprintf(_('The selected files type should be %s.'), $type)); + return false; + } else { + return true; + } + } + + /** + * + * @param mixed $file + * @param mixed $type + * @return boolean + */ + public function file_disallowed_type($file, $type) { + $rc = $this->file_allowed_type($file, $type); + if (!$rc) { + $this->set_message('file_disallowed_type', sprintf(_('The selected file cannot be %s.'), $type)); + } + return $rc; + } + + /** + * Returns FALSE if image is bigger than the given dimensions. + * + * @param mixed $file + * @param array $dim + * @return boolean + */ + public function file_image_maxdim($file, $dim) { + log_message('debug', "MY_Form_validation::file_image_maxdim() " . $dim); + $dim = explode(',', $dim); + + if (count($dim) !== 2) { + // bad size given + $this->set_message('file_image_maxdim', "%s has invalid rule expected similar to 150,300 ."); + return false; + } + + log_message('debug', 'MY_Form_validation::file_image_maxdim() ' . $dim[0] . ' ' . $dim[1]); + + // get image size + $d = $this->getImageDimensions($file['tmp_name']); + + log_message('debug', $d[0] . ' ' . $d[1]); + + if (!$d) { + $this->set_message('file_image_maxdim', "%s dimensions was not detected."); + return false; + } + + if ($d[0] < $dim[0] && $d[1] < $dim[1]) { + return true; + } + + $this->set_message('file_image_maxdim', "%s image size is too big."); + return false; + } + + /** + * Returns FALSE is the image is smaller than the given dimension. + * + * @param mixed $file + * @param array $dim + * @return boolean + */ + public function file_image_mindim($file, $dim) { + $dim = explode(',', $dim); + + if (count($dim) !== 2) { + // bad size given + $this->set_message('file_image_mindim', "%s has invalid rule expected similar to 150,300 ."); + return false; + } + + // get image size + $d = $this->getImageDimensions($file['tmp_name']); + + if (!$d) { + $this->set_message('file_image_mindim', "%s dimensions was not detected."); + return false; + } + + log_message('debug', $d[0] . ' ' . $d[1]); + + if ($d[0] > $dim[0] && $d[1] > $dim[1]) { + return true; + } + + $this->set_message('file_image_mindim', "%s image size is too big."); + return false; + } + + /** + * Attempts to determine the image dimension. + * + * @param mixed $filename The path to the image file + * @return mixed + */ + private function getImageDimensions($filename) { + log_message('debug', $filename); + + if (function_exists('getimagesize')) { + $d = @getimagesize($filename); + return $d; + } + return false; + } } diff --git a/application/views/projects/new.php b/application/views/projects/new.php index 259e64c..27c4f28 100644 --- a/application/views/projects/new.php +++ b/application/views/projects/new.php @@ -1,53 +1,51 @@ -load->view('header'); ?> +load->view('header');?>