diff --git a/fapi_validation.module b/fapi_validation.module
index 838a36dbc1394ee1044fcb8aa8d5cce57df4cd4c..999fde4dde35332de9296686190a08512eb1a5fb 100644
--- a/fapi_validation.module
+++ b/fapi_validation.module
@@ -4,6 +4,10 @@
  * Implementation of hook_form_alter
  */
 function fapi_validation_form_alter(&$form, $form_state, $form_id) {
+  if (!isset($form['#validate']) || !is_array($form['#validate'])) {
+    $form['#validate'] = array();
+  }
+
   $form['#validate'] = array_merge(array('fapi_validation_form_validate'), $form['#validate']);
 }
 
@@ -11,18 +15,19 @@ function fapi_validation_form_alter(&$form, $form_state, $form_id) {
  * Validate the form searching for #rules and #filters params.
  */
 function fapi_validation_form_validate(&$form, &$form_state) {
+  // Initializing register
+  fapi_validation_register($form, NULL, $form_state);
+  // Starting validation process
   _fapi_validation_element_validate($form, $form_state);
-    
-  foreach (fapi_validation_register() as $key => $value) {
-    form_set_value($form[$key], $value, $form_state);
-  }
+  // Updating $form_state
+  $form_state = fapi_validation_register($form);
 }
 
 function _fapi_validation_element_validate(&$elements, $child=FALSE) {
   if (isset($elements['#filters'])) {
     fapi_validation_filters_execute($elements);
   }
-  
+
   if (isset($elements['#rules'])) {
     fapi_validation_rules_execute($elements);
   }    
@@ -35,37 +40,87 @@ function _fapi_validation_element_validate(&$elements, $child=FALSE) {
   return $values;
 }
 
-function fapi_validation_register($key=NULL, $value=NULL) {
-  static $register = array();
-  if (!is_null($key)) {
-    $register[$key] = $value;
+function fapi_validation_register(&$element=NULL, $value=NULL, $form_state=NULL) {
+  static $fs;
+  
+  if (!is_null($form_state)) {
+    $fs = $form_state;
+  }
+  
+  if (!is_null($element) && !is_null($value)) {
+    form_set_value($element, $value, $fs);
+    $element['#value'] = $value;
+  }
+  else {
+    return $fs;
   }
-  return $register;
 }
 
-function fapi_validation_filters_execute($elements) {
+function fapi_validation_filters_execute(&$element) {
   $data = _fapi_validation_data('filters');
-  
-  $value = $elements['#value'];
-  foreach($elements['#filters'] as $filter) {
+
+  if (!isset($element['#value'])) {
+    return;
+  }
+
+  $value = $element['#value'];
+  foreach ($element['#filters'] as $filter) {
     if (!isset($data[$filter])) {
       continue;
     }
     $value = $data[$filter]['callback']($value);
   }
-  fapi_validation_register($elements['#name'], $value);
+  fapi_validation_register($element, $value);
 }
 
-function fapi_validation_rules_execute($elements) {
-  $data = _fapi_validation_data('rule');
-  
-  foreach($elements['#rules'] as $rule) {
+function fapi_validation_rules_execute(&$element) {
+  $data = _fapi_validation_data('rules');
+
+  // If element is empty and not required, by pass rule validation.
+  if (!$element['#required'] && empty($element['#value'])) {
+    return;
+  }
+
+  foreach ($element['#rules'] as $rule) {
+    $params = array($element['#value']);
+    $error_message = NULL;
+
+    // If $rule is an array, use error message if is setted.
+    if (is_array($rule)) {
+      if (isset($rule['error'])) {
+        $error_message = $rule['error'];
+      }
+
+      if (!isset($rule['rule'])) {
+        drupal_set_message(t('Rule array with wrong structure on %field.', array('%field' => $element['#name'])), 'error');
+        continue;
+      }
+      $rule = $rule['rule'];
+    }
+    
+    preg_match('/^(.*?)(\[(.*)\])?$/', $rule, $rs);
+    
+    $rule = $rs[1];
+   
     if (!isset($data[$rule])) {
+      drupal_set_message(t('Rule %rule not found!', array('%rule' => $rule)), 'error');
       continue;
     }
-    $ret = $data[$rule]['callback']($elements['#value']);
+
+    // Parsing parameters.
+    if (isset($rs[3])) {
+      if ($rule == 'regexp') {
+        $params[] = array($rs[3]);
+      }
+      else {
+        $params[] = preg_split('/ *, */', $rs[3]);
+      }
+    }
+    
+    $ret = call_user_func_array($data[$rule]['callback'], $params);
     if (!$ret) {
-      form_set_error($elements['#name'], t($data[$rule]['error_msg'], array('%field'=>$elements['#title'])));
+      $error = is_null($error_message) ? $data[$rule]['error_msg'] : $error_message;
+      form_set_error($element['#name'], t($error, array('%field' => $element['#title'])));
     }
   }
 }
@@ -73,9 +128,9 @@ function fapi_validation_rules_execute($elements) {
 function _fapi_validation_data($type, $refresh=NULL) {
   static $data = array();
   
-  if (!count($data[$type]) || $refresh) {
-    foreach (module_implements('fapi_validation_'.$type) as $module) {
-      $validations = module_invoke($module, 'fapi_validation_'.$type);
+  if (!isset($data[$type]) || !count($data[$type]) || $refresh) {
+    foreach (module_implements('fapi_validation_' . $type) as $module) {
+      $validations = module_invoke($module, 'fapi_validation_' . $type);
       if (isset($validations) && is_array($validations)) {
         foreach ($validations as $name => $info) {
           $data[$type][$name] = $info;
@@ -87,27 +142,65 @@ function _fapi_validation_data($type, $refresh=NULL) {
   return $data[$type];
 }
 
+/**
+ * Implementation of hook_fapi_validation_rules
+ */
 function fapi_validation_fapi_validation_rules() {
   return array(
     'numeric' => array(
       'callback' => 'fapi_validation_rule_numeric',
-      'error_msg' => 'Use only numbers at %field.'
+      'error_msg' => t('Use only numbers at %field.')
     ),
     'alpha' => array(
       'callback' => 'fapi_validation_rule_alpha',
-      'error_msg' => 'Use only alpha characters at %field.'
+      'error_msg' => t('Use only alpha characters at %field.')
     ),
     'alpha_numeric' => array(
       'callback' => 'fapi_validation_rule_alpha_numeric',
-      'error_msg' => 'Use only alpha numerics characters at %field.'
+      'error_msg' => t('Use only alpha numerics characters at %field.')
     ),
     'email' => array(
       'callback' => 'fapi_validation_rule_email',
-      'error_msg' => 'The field %field not is a valid email.'
+      'error_msg' => t('%field not is a valid email.')
+    ),
+    'length' => array(
+      'callback' => 'fapi_validation_rule_length',
+      'error_msg' => t('Invalid size of %field value.')
+    ),
+    'chars' => array(
+      'callback' => 'fapi_validation_rule_chars',
+      'error_msg' => t('Invalid characters on %field value.')
+    ),
+    'url' => array(
+      'callback' => 'fapi_validation_rule_url',
+      'error_msg' => t('Invalid format of %field.')
+    ),
+    'ipv4' => array(
+      'callback' => 'fapi_validation_rule_ipv4',
+      'error_msg' => t('Invalid format of %field.')
+    ),
+    'alpha_dash' => array(
+      'callback' => 'fapi_validation_rule_alpha_dash',
+      'error_msg' => t('Use only alpha numerics, hyphen and underscore at %field.')
+    ),
+    'digit' => array(
+      'callback' => 'fapi_validation_rule_digit',
+      'error_msg' => t('Use only digits on %field.')
+    ),
+    'decimal' => array(
+      'callback' => 'fapi_validation_rule_decimal',
+      'error_msg' => t('Use only decimal on %field.')
+    ),
+    'regexp' =>  array(
+      'callback' => 'fapi_validation_rule_regexp',
+      'error_msg' => t('%field value does not match rule.')
     ),
   );
 }
 
+/**
+ * Implementation of hook_fapi_validation_filters
+ */
 function fapi_validation_fapi_validation_filters() {
   return array(
     'numeric' => array(
@@ -116,6 +209,12 @@ function fapi_validation_fapi_validation_filters() {
     'trim' => array(
       'callback' => 'fapi_validation_filter_trim',
     ),
+    'uppercase' => array(
+      'callback' => 'fapi_validation_filter_uppercase',
+    ),
+    'lowercase' => array(
+      'callback' => 'fapi_validation_filter_lowercase',
+    ),
   );
 }
 
@@ -136,9 +235,63 @@ function fapi_validation_rule_alpha_numeric($value) {
 }
 
 function fapi_validation_rule_email($value) {
-  return valid_email_addess($value);
+  return valid_email_address($value);
+}
+
+function fapi_validation_rule_length($value, $params) {
+  $size = mb_strlen($value);
+  if (count($params) == 1) {
+    return $size == (int) $params[0];
+  }
+  elseif (count($params) == 2) {
+    return ($size >= (int) $params[0] && $size <= (int) $params[1]);
+  }
+}
+
+function fapi_validation_rule_url($value, $params = array()) {
+  return valid_url($value, !empty($params) && $params[0] == 'absolute');
+}
+
+function fapi_validation_rule_ipv4($value) {
+  $pattern = '/^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])'
+    . '(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$/';
+  return (bool) preg_match($pattern, $value);
+}
+
+function fapi_validation_rule_alpha_dash($value) {
+  return (bool) preg_match('/^[-\pL\pN_]+$/uD', (string) $value);
 }
 
+function fapi_validation_rule_digit($value) {
+  return (bool) preg_match('/^\d+$/', $value);
+}
+
+function fapi_validation_rule_chars($value, $params) {
+  for ($i = 0; $i < mb_strlen($value); $i++) {
+    $current = substr($value, $i, 1);
+    if (! in_array($current, $params)) {
+      return FALSE;
+    }
+  }
+  return TRUE;
+}
+
+function fapi_validation_rule_decimal($value, $params) {
+  if (count($params) == 2) {
+    $pattern = '/^[0-9]{' . $params[0] . '}\.[0-9]{' . $params[1] . '}$/';
+    return (bool) preg_match($pattern, (string) $value);
+  }
+  else {
+    return (bool) preg_match('/\d+\.\d+/', $value);
+  }
+  return FALSE;
+}
+
+function fapi_validation_rule_regexp($value, $params) {
+  return (bool) preg_match($params[0], (string) $value);
+}
+
+
 /**
  * Filters
  */
@@ -149,4 +302,12 @@ function fapi_validation_filter_numeric($value) {
 
 function fapi_validation_filter_trim($value) {
   return trim($value);
-}
\ No newline at end of file
+}
+
+function fapi_validation_filter_uppercase($value) {
+  return mb_strtoupper($value);
+}
+
+function fapi_validation_filter_lowercase($value) {
+  return mb_strtolower($value);
+}