diff --git a/metatags_quick.admin.inc b/metatags_quick.admin.inc
old mode 100644
new mode 100755
index 584368d..718205e
--- a/metatags_quick.admin.inc
+++ b/metatags_quick.admin.inc
@@ -1,340 +1,683 @@
-<?php
-function metatags_quick_admin_settings() {
-  $current_settings = variable_get('metatags_quick_settings', _metatags_quick_settings_default());
-  $module_path = drupal_get_path('module', 'metatags_quick');
-  $fields = field_info_fields();
-  $metatags_found = FALSE;
-
-  include_once $module_path . '/known_tags.inc';
-  $known_tags = _metatags_quick_known_fields();
-  
-  $form['path_based'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Path-based meta tags'),
-    '#collapsible' => TRUE,
-    '#collapsed' => TRUE,
-  );
-
-  foreach ($fields as $key => $field) {
-    if ($field['module'] != 'metatags_quick') {
-      continue;
-    }
-    $metatags_found = TRUE;
-  }
-  if (!$metatags_found) {
-    $form['path_based']['basic_init'] = array(
-      '#markup' => t('No meta tags found in your installation') . '<br/>',
-    );
-  }
-  
-  $form['path_based']['use_path_based'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Use path-based meta tags'),
-    '#default_value' => variable_get('metatags_quick_use_path_based', 1),
-    '#return_value' => 1,
-  );
-  
-  $form['standard_tags'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Create and attach'),
-    '#description' => t('The following meta tags are known to the module and can be created automatically. However, you are not limited to this list and can define tags of your own using the Fields UI.'),
-    '#collapsible' => TRUE,
-    '#attached' => array(
-      'js' => array($module_path . '/js/admin.js'),
-      'css' => array($module_path . '/css/admin.css'),
-    ),
-  );
-  $form['standard_tags']['hint'] = array(
-    '#markup' => t('Hint: press on the bundle name to see individual entity types'),
-  );
-  
-  $field_instances = field_info_instances();
-
-  // Build the sortable table header.
-  $header = array(
-    'title' => array('data' => t('Bundle/entity')),
-  );
-  foreach ($known_tags as $name => $tag) {
-    $header[$name] = $tag['title'];
-  }
-  //$header['_select_all'] = t('Select all');
-  
-  foreach (field_info_bundles() as $entity_type => $bundles) {
-    $entity_info = entity_get_info($entity_type);
-    if (!$entity_info['fieldable']) {
-      continue;
-    }
-    $options[$entity_type]['data'] = array(
-      'title' => array(
-        'class' => array('entity_type_collapsible', 'entity_type_collapsed', "entity_name_$entity_type"),
-        'data' => $entity_info['label']
-      )
-    );
-    foreach ($known_tags as $name => $tag) {
-      $bundle_workable[$name] = FALSE;
-      $options[$entity_type]['data'][$name] = array(
-        'data' => array(
-          '#type' => 'checkbox',
-          '#attributes' => array('class' => array('cb_bundle_parent', "cb_bundle_name_{$entity_type}_{$name}")),      
-          '#return_value' => 1,
-          '#checked' => FALSE,
-        ),
-      );
-    }
-    /*$options[$entity_type]['data']['_select_all'] = array(
-      'data' => array(
-      '#type' => 'checkbox',
-      '#return_value' => 1,
-      '#checked' => FALSE,
-      ),
-    );*/
-    
-    // How do we mark that specific meta is already attached to bundle
-    $checked_markup = array(
-      '#markup' => theme('image', 
-        array(
-          'path' => 'misc/watchdog-ok.png',
-          'width' => 18,
-          'height' => 18,
-          'alt' => 'ok',
-          'title' => 'ok',
-        )),
-    );
-        
-    foreach ($bundles as $key => $bundle) {
-      // Which meta tags are set for this bundle?
-      $meta_set = array();
-      foreach ($field_instances[$entity_type][$key] as $bundle_instance) {
-        if ($bundle_instance['widget']['module'] == 'metatags_quick') {
-          $field_info = field_info_field_by_id($bundle_instance['field_id']);
-          $meta_set[$field_info['settings']['meta_name']] = 1;
-        }        
-      }
-      
-      $options[$entity_type . '_' . $key] = array(
-        'class' => array('entity_type_children', "entity_child_$entity_type"),
-        'style' => 'display: none',
-        'data' => array(
-          'title' => array(
-            'class' => array('entity_type_child_title'),
-            'data' => $bundle['label'],
-          ),
-        ),
-      );
-      foreach ($known_tags as $name => $tag) {
-        if (empty($meta_set[$name])) {
-          // Mark parent bundle as workable - display checkbox.
-          $bundle_workable[$name] = TRUE;
-          $options[$entity_type . '_' . $key]['data'][$name] = array(
-            'data' => array(
-              '#name' => $entity_type . '[' . $key . '][' . $name . ']',
-              '#type' => 'checkbox',
-              '#attributes' => array('class' => array('cb_bundle_child', "cb_child_{$entity_type}_{$name}")),
-              '#return_value' => 1,
-              '#checked' => FALSE,
-            )
-          );
-        }
-        else {
-          $options[$entity_type . '_' . $key]['data'][$name]['data'] = $checked_markup; 
-        }
-      }
-      /*$options[$entity_type . '_' . $key]['data']['_select_all']['data'] = array(
-        '#type' => 'checkbox',
-        '#return_value' => 1,
-        '#checked' => FALSE,
-      );*/
-    }
-    // Now check if we have completely set bundles
-    foreach ($known_tags as $name => $tag) {
-      if (!$bundle_workable[$name]) {
-        $options[$entity_type]['data'][$name]['data'] = $checked_markup; 
-      }
-    }
-  }
-  
-  $form['standard_tags']['existing'] = array(
-    '#theme' => 'table',
-    '#header' => $header,
-    '#rows' => $options,
-    '#empty' => t('No content available.'),
-  );
-  
-  $form['standard_tags']['basic_init_op'] = array(
-    '#type' => 'submit',
-    '#value' => t('Attach'),
-  );
-    
-  $form['op'] = array(
-    '#value' => t('Submit'),
-    '#type' => 'submit', 
-  );
-  return $form;
-}
-
-function metatags_quick_admin_settings_submit($form, &$form_state) {
-  variable_set('metatags_quick_use_path_based', $form_state['values']['use_path_based']);
-  if ($form_state['clicked_button']['#value'] == t('Attach')) {
-    _metatags_quick_admin_fields_create_attach($form_state['input']);
-  }
-  else {
-  }
-  drupal_set_message(t('Meta tags (quick) settings saved'), 'status');
-}
-
-/**
- * Path based form callback
- */
-function metatags_quick_admin_path_page() {
-  if (!empty($_GET['path']) && !empty($_GET['lang'])) {
-    return drupal_get_form('metatags_quick_admin_path', $_GET['lang'], $_GET['path']);
-  }
-  else {
-    return MENU_ACCESS_DENIED;
-  }
-}
-
-/*
- * Path-based meta tags editing form.
- * @param string $path - path being edited.
- */
-function metatags_quick_admin_path($form, &$form_state) {
-  $args = func_get_args();
-  if (count($args) > 3) {
-    $lang = $args[2];
-    $path = $args[3];
-  }
-  else {
-    return MENU_ACCESS_DENIED;
-  }
-  
-  $controller = new DrupalDefaultEntityController('metatags_path_based');
-  $entity_id = db_select('metatags_quick_path_based', 'm')
-    ->fields('m', array('id'))
-    ->condition('lang', $lang)
-    ->condition('path', $path)
-    ->execute()
-    ->fetchField();
-  if (!$entity_id) {
-    $entity_id = db_insert('metatags_quick_path_based')
-      ->fields(array('lang' => $lang, 'path' => $path))
-      ->execute();
-  }
-  $entities = $controller->load(array($entity_id));
-  $form_state['entity'] = $entities[$entity_id];
-  field_attach_form('metatags_path_based', $entities[$entity_id], $form, $form_state);
-  // Do we have any fields attached?
-  $childen = element_children($form);
-  if (!$childen) {
-    $form['empty_message'] = array(
-      '#markup' => t('No fields attached to the path-based meta tags. Please !define them first in the module settings screen',
-        array('!define' => l(t('define'), 'admin/config/search/metatags_quick'))) . '<br/>',
-    );
-  }
-  $form['op'] = array(
-    '#value' => t('Submit'),
-    '#type' => 'submit', 
-  );  
-  return $form;
-}
-
-function metatags_quick_admin_path_validate($form, &$form_state) {
-  entity_form_field_validate('metatags_path_based', $form, $form_state);
-}
-
-function metatags_quick_admin_path_submit($form, &$form_state) {
-  if (!$form_state['entity']) {
-    form_set_error();
-    drupal_set_message(t('Wrong path'), 'error');
-    return;
-  }
-  
-  $entity = $form_state['entity'];
-  entity_form_submit_build_entity('metatags_path_based', $entity, $form, $form_state);
-  field_attach_update('metatags_path_based', $entity);
-  
-  drupal_set_message('Meta tags updated', 'status');
-  $form_state['redirect'] = FALSE;
-}
-
-// Create known meta fields.
-function _metatags_quick_admin_fields_create_attach($input) {
-  foreach (field_info_bundles() as $entity_type => $bundles) {
-    $entity_info = entity_get_info($entity_type);
-    if (!$entity_info['fieldable']) {
-      continue;
-    }
-    
-    foreach ($bundles as $key => $bundle) {
-      if (isset($input[$entity_type][$key])) {
-        foreach ($input[$entity_type][$key] as $meta_name => $meta_value) {
-          _metatags_quick_field_attach($entity_type, $key, $meta_name);
-        }
-      }
-    }
-  }
-}
-  
-function _metatags_quick_field_attach($entity_type, $bundle, $meta_name) {
-  static $meta_fields = FALSE;
-  static $field_id = array();
-  static $known_tags = FALSE;
-  
-  // Get metatags_quick fields info
-  if (!$meta_fields) {
-    include_once drupal_get_path('module', 'metatags_quick') . '/known_tags.inc';
-    $known_tags = _metatags_quick_known_fields();
-    
-    foreach(field_info_fields() as $name => $field_info) {
-      if ($field_info['module'] == 'metatags_quick') {
-        $meta_fields[$field_info['settings']['meta_name']] = $field_info;
-        $field_id[$field_info['settings']['meta_name']] = $field_info['id'];
-      }
-    }
-  }
-  
-    // Ignore unknown tags.
-  if (!isset($known_tags[$meta_name])) {
-    return;
-  }
-  
-  // Check if meta field exists, create if necessary.
-  if (empty($field_id[$meta_name])) {
-    $field = array(
-      'field_name' => "meta_$meta_name", 
-      'type' => 'metatags_quick', 
-      'module' => 'metatags_quick',
-      'settings' => array('meta_name' => (isset($known_tags[$meta_name]['meta_name']) ? $known_tags[$meta_name]['meta_name'] : $meta_name)), 
-      'cardinality' => 1,
-    );
-    $field = field_create_field($field);
-    $field_id[$meta_name] = $field['id'];
-    $meta_fields[$meta_name] = $field;
-  }
-  else {
-    $field = $meta_fields[$meta_name];
-  }
-  
-  // Do nothing if instance already exists.
-  if (isset($field['bundles'][$entity_type])
-    && in_array($bundle, $field['bundles'][$entity_type])) {
-    return;
-  }
-  
-  // Now create field instance attached to requested bundle
-  $instance = array(
-    'field_name' => $field['field_name'],
-    'entity_type' => $entity_type,
-    'bundle' => $bundle,
-    'label' => $known_tags[$meta_name]['title'],
-    'formatter' => 'metatags_quick_default',
-    'widget' => array(
-      'type' => $known_tags[$meta_name]['widget'],
-      'weight' => 0,
-    ),
-  );
-  if (isset($known_tags[$meta_name]['options'])) {
-    $instance['settings']['options'] = $known_tags[$meta_name]['options'];
-  }
-  field_create_instance($instance);
-}
+<?php
+/**
+ * General administration form for metagtags
+ *
+ * @return string 
+ */
+function metatags_quick_admin_settings() {
+  $current_settings = variable_get('metatags_quick_settings', _metatags_quick_settings_default());
+  $module_path = drupal_get_path('module', 'metatags_quick');
+  $fields = field_info_fields();
+  $metatags_found = FALSE;
+
+  include_once $module_path . '/known_tags.inc';
+  $known_tags = _metatags_quick_known_fields();
+  
+  $form['standard_tags'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Create and attach'),
+    '#description' => t('The following meta tags are known to the module and can be created automatically. However, you are not limited to this list and can define tags of your own using the Fields UI.'),
+    '#collapsible' => TRUE,
+    '#attached' => array(
+      'js' => array($module_path . '/js/admin.js'),
+      'css' => array($module_path . '/css/admin.css'),
+    ),
+  );
+  $form['standard_tags']['hint'] = array(
+    '#markup' => t('Hint: press on the bundle name to see individual entity types'),
+  );
+  
+  $field_instances = field_info_instances();
+
+  // Build the sortable table header.
+  $header = array(
+    'title' => array('data' => t('Bundle/entity')),
+  );
+  foreach ($known_tags as $name => $tag) {
+    $header[$name] = $tag['title'];
+  }
+  //$header['_select_all'] = t('Select all');
+  
+  foreach (field_info_bundles() as $entity_type => $bundles) {
+    $entity_info = entity_get_info($entity_type);
+    if (!$entity_info['fieldable']) {
+      continue;
+    }
+    $options[$entity_type]['data'] = array(
+      'title' => array(
+        'class' => array('entity_type_collapsible', 'entity_type_collapsed', "entity_name_$entity_type"),
+        'data' => $entity_info['label']
+      )
+    );
+    foreach ($known_tags as $name => $tag) {
+      $bundle_workable[$name] = FALSE;
+      $options[$entity_type]['data'][$name] = array(
+        'data' => array(
+          '#type' => 'checkbox',
+          '#attributes' => array('class' => array('cb_bundle_parent', "cb_bundle_name_{$entity_type}_{$name}")),      
+          '#return_value' => 1,
+          '#checked' => FALSE,
+        ),
+      );
+    }
+    /*$options[$entity_type]['data']['_select_all'] = array(
+      'data' => array(
+      '#type' => 'checkbox',
+      '#return_value' => 1,
+      '#checked' => FALSE,
+      ),
+    );*/
+    
+    // How do we mark that specific meta is already attached to bundle
+    $checked_markup = array(
+      '#markup' => theme('image', 
+        array(
+          'path' => 'misc/watchdog-ok.png',
+          'width' => 18,
+          'height' => 18,
+          'alt' => 'ok',
+          'title' => 'ok',
+        )),
+    );
+        
+    foreach ($bundles as $key => $bundle) {
+      // Which meta tags are set for this bundle?
+      $meta_set = array();
+      foreach ($field_instances[$entity_type][$key] as $bundle_instance) {
+        if ($bundle_instance['widget']['module'] == 'metatags_quick') {
+          $field_info = field_info_field_by_id($bundle_instance['field_id']);
+          $meta_set[$field_info['settings']['meta_name']] = 1;
+        }        
+      }
+      
+      $options[$entity_type . '_' . $key] = array(
+        'class' => array('entity_type_children', "entity_child_$entity_type"),
+        'style' => 'display: none',
+        'data' => array(
+          'title' => array(
+            'class' => array('entity_type_child_title'),
+            'data' => $bundle['label'],
+          ),
+        ),
+      );
+      foreach ($known_tags as $name => $tag) {
+        if (empty($meta_set[$name])) {
+          // Mark parent bundle as workable - display checkbox.
+          $bundle_workable[$name] = TRUE;
+          $options[$entity_type . '_' . $key]['data'][$name] = array(
+            'data' => array(
+              '#name' => $entity_type . '[' . $key . '][' . $name . ']',
+              '#type' => 'checkbox',
+              '#attributes' => array('class' => array('cb_bundle_child', "cb_child_{$entity_type}_{$name}")),
+              '#return_value' => 1,
+              '#checked' => FALSE,
+            )
+          );
+        }
+        else {
+          $options[$entity_type . '_' . $key]['data'][$name]['data'] = $checked_markup; 
+        }
+      }
+      /*$options[$entity_type . '_' . $key]['data']['_select_all']['data'] = array(
+        '#type' => 'checkbox',
+        '#return_value' => 1,
+        '#checked' => FALSE,
+      );*/
+    }
+    // Now check if we have completely set bundles
+    foreach ($known_tags as $name => $tag) {
+      if (!$bundle_workable[$name]) {
+        $options[$entity_type]['data'][$name]['data'] = $checked_markup; 
+      }
+    }
+  }
+  
+  $form['standard_tags']['existing'] = array(
+    '#theme' => 'table',
+    '#header' => $header,
+    '#rows' => $options,
+    '#empty' => t('No content available.'),
+  );
+  
+  $form['standard_tags']['basic_init_op'] = array(
+    '#type' => 'submit',
+    '#value' => t('Attach'),
+  );
+  
+  $form['path_based'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Path-based meta tags'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+  );
+
+  foreach ($fields as $key => $field) {
+    if ($field['module'] != 'metatags_quick') {
+      continue;
+    }
+    $metatags_found = TRUE;
+  }
+  if (!$metatags_found) {
+    $form['path_based']['basic_init'] = array(
+      '#markup' => t('No meta tags found in your installation') . '<br/>',
+    );
+  }
+  
+  $form['path_based']['use_path_based'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Use path-based meta tags'),
+    '#default_value' => variable_get('metatags_quick_use_path_based', 0),
+    '#return_value' => 1,
+  );
+  
+  
+  $form['op'] = array(
+    '#value' => t('Submit'),
+    '#type' => 'submit', 
+  );
+  return $form;
+}
+
+function metatags_quick_admin_settings_submit($form, &$form_state) {
+  variable_set('metatags_quick_use_path_based', $form_state['values']['use_path_based']);
+  if ($form_state['clicked_button']['#value'] == t('Attach')) {
+    _metatags_quick_admin_fields_create_attach($form_state['input']);
+  }
+  else {
+  }
+  drupal_set_message(t('Meta tags (quick) settings saved'), 'status');
+}
+
+/**
+ * Path based form callback
+ */
+function metatags_quick_admin_path_page() {
+  if (!empty($_GET['path']) && !empty($_GET['lang'])) {
+    return drupal_get_form('metatags_quick_admin_path', $_GET['lang'], $_GET['path']);
+  }
+  else {
+    return MENU_ACCESS_DENIED;
+  }
+}
+
+/*
+ * Path-based meta tags editing form.
+ * @param string $path - path being edited.
+ */
+function metatags_quick_admin_path($form, &$form_state) {
+  $args = func_get_args();
+  if (count($args) > 3) {
+    $lang = $args[2];
+    $path = $args[3];
+  }
+  else {
+    return MENU_ACCESS_DENIED;
+  }
+  
+  $controller = new DrupalDefaultEntityController('metatags_path_based');
+  $entity_id = db_select('metatags_quick_path_based', 'm')
+    ->fields('m', array('id'))
+    ->condition('lang', $lang)
+    ->condition('path', $path)
+    ->execute()
+    ->fetchField();
+  if (!$entity_id) {
+    $entity_id = db_insert('metatags_quick_path_based')
+      ->fields(array('lang' => $lang, 'path' => $path))
+      ->execute();
+  }
+  $entities = $controller->load(array($entity_id));
+  $form_state['entity'] = $entities[$entity_id];
+  field_attach_form('metatags_path_based', $entities[$entity_id], $form, $form_state);
+  $form['op'] = array(
+    '#value' => t('Submit'),
+    '#type' => 'submit', 
+  );  
+  return $form;
+}
+
+function metatags_quick_admin_path_validate($form, &$form_state) {
+  entity_form_field_validate('metatags_path_based', $form, $form_state);
+}
+
+function metatags_quick_admin_path_submit($form, &$form_state) {
+  if (!$form_state['entity']) {
+    form_set_error();
+    drupal_set_message(t('Wrong path'), 'error');
+    return;
+  }
+  
+  $entity = $form_state['entity'];
+  entity_form_submit_build_entity('metatags_path_based', $entity, $form, $form_state);
+  field_attach_update('metatags_path_based', $entity);
+  
+  drupal_set_message('Meta tags updated', 'status');
+  if(isset($_GET['destination']))
+    $form_state['redirect'] = $_GET['destination'];
+  else 
+    $form_state['redirect'] = FALSE;
+}
+
+// Create known meta fields.
+function _metatags_quick_admin_fields_create_attach($input) {
+  foreach (field_info_bundles() as $entity_type => $bundles) {
+    $entity_info = entity_get_info($entity_type);
+    if (!$entity_info['fieldable']) {
+      continue;
+    }
+    
+    foreach ($bundles as $key => $bundle) {
+      if (isset($input[$entity_type][$key])) {
+        foreach ($input[$entity_type][$key] as $meta_name => $meta_value) {
+          _metatags_quick_field_attach($entity_type, $key, $meta_name);
+        }
+      }
+    }
+  }
+}
+  
+function _metatags_quick_field_attach($entity_type, $bundle, $meta_name) {
+  static $meta_fields = FALSE;
+  static $field_id = array();
+  static $known_tags = FALSE;
+  
+  // Get metatags_quick fields info
+  if (!$meta_fields) {
+    include_once drupal_get_path('module', 'metatags_quick') . '/known_tags.inc';
+    $known_tags = _metatags_quick_known_fields();
+    
+    foreach(field_info_fields() as $name => $field_info) {
+      if ($field_info['module'] == 'metatags_quick') {
+        $meta_fields[$field_info['settings']['meta_name']] = $field_info;
+        $field_id[$field_info['settings']['meta_name']] = $field_info['id'];
+      }
+    }
+  }
+  
+  // Check if meta field exists, create if necessary.
+  if (empty($field_id[$meta_name])) {
+    // @todo: check if there is $known_tags[$meta_name]?
+    // @todo: check for existing meta_* field (while is unlikely, but still possible).
+    $field = array(
+      'field_name' => "meta_$meta_name", 
+      'type' => 'metatags_quick', 
+      'module' => 'metatags_quick',
+      'settings' => array('meta_name' => $meta_name), 
+      'cardinality' => 1,
+    );
+    $field = field_create_field($field);
+    $field_id[$meta_name] = $field['id'];
+    $meta_fields[$meta_name] = $field;
+  }
+  else {
+    $field = $meta_fields[$meta_name];
+  }
+
+  // Now create field instance attached to requested bundle
+  $instance = array(
+    'field_name' => $field['field_name'],
+    'entity_type' => $entity_type,
+    'bundle' => $bundle,
+    'label' => $known_tags[$meta_name]['title'],
+    'formatter' => 'metatags_quick_default',
+    'widget' => array(
+      'type' => $known_tags[$meta_name]['widget'],
+      'weight' => 0,
+    ),
+  );
+  field_create_instance($instance);
+}
+
+/**
+ * Display all pathes that have metagtags defined for them
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags($form, $form_state) {
+  // get current language and module path
+  global $language;
+  $module_path = drupal_get_path('module', 'metatags_quick');
+  // grab language list
+  $languages = _metatags_quick_language_list();
+  // create table form
+  $form['new_path_based'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('New path'),
+    '#collapsible' => FALSE,
+    '#attached' => array(
+      'js' => array($module_path . '/js/admin.js'),
+      'css' => array($module_path . '/css/admin.css'),
+    ),
+    'new_path' => array(
+      '#tpye' => 'container',
+      '#prefix' => '<div style="float:left">',
+      '#suffix' => '</div><div style="clear:both;"> </div>',
+      'path' => array(
+        '#type' => 'textfield',
+        '#title' => t('Path:'),
+        '#description' => t('Enter path starting without a leading "/". "*" can be used as a wildcard at the end of a path.'),
+        '#prefix' => '<div style="float:left;">',
+        '#suffix' => '</div>',
+      ),
+      'language' => array(
+        '#type' => 'select',
+        '#title' => 'Select language',
+        '#options' => $languages,
+        '#default_value' => $language->language,
+        '#prefix' => '<div style="float:left; margin-left: 40px;">',
+        '#suffix' => '</div><div style="clear:both;"> </div>',
+      ),
+      'new_path_submit' => array(
+        '#type' => 'submit',
+        '#value' => t('Create'),
+        '#attributes' => array('style' => 'margin-bottom: 20px;')
+      )
+    )
+  );
+  $form['path_based'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Manage Paths'),
+    '#collapsible' => FALSE
+  );
+  $header = array(
+    'path' => array('data' => t('Path'), 'field' => 'p.path'),
+    'language' => array('data' => t('Language'), 'field' => 'p.lang', 'width' => '10%'),
+    'operations' => array('data' => t('Operations'), 'width' => '30%', 'colspan' => 2),
+  );
+  $query = db_select('metatags_quick_path_based', 'p')->extend('PagerDefault')->extend('TableSort');
+  $result = $query
+   ->fields('p')
+   ->limit(50)
+   ->orderByHeader($header)
+   ->execute();
+  // set up to fill options array
+  $destination = drupal_get_destination();
+  $options = array();
+  // fill options array
+  foreach ($result as $path) {
+    $options[] = array(
+      'path' => l($path->path, $path->path, array('query' => $destination)),
+      'language' =>  $languages[check_plain($path->lang)],
+      'edit' =>
+        l(t('edit'), 
+           'admin/config/search/metatags_quick/path_based_metatags/edit', 
+           array('query' => array('path' => $path->path, 'lang' => $path->lang, 'destination' => $destination['destination']))),
+      'delete' =>
+        l(t('delete'), 
+           'admin/config/search/metatags_quick/path_based_metatags/delete', 
+           array('query' => array('path' => $path->path, 'lang' => $path->lang, 'destination' => $destination['destination'])))
+    );
+  }
+  // add created table
+  $form['path_based']['existing'] = array(
+    '#theme' => 'table',
+    '#header' => $header,
+    '#rows' => $options,
+    '#empty' => t('No content available.'),
+    '#attributes' => array('id' => 'path_based_metatags'),
+  );
+  // add default page
+  $form['path_based']['pager'] = array('#markup' => theme('pager', array('tags' => NULL)));
+  // return listing form
+  return $form;
+}
+
+/**
+ * Validates the existance of a valid path provided by the user. Path has to be
+ * at least 2 characters long.
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_validate($form, $form_state) {
+  if(isset($form_state['values']['path'])) {
+    // create path and empty entity
+    if(strlen(trim($form_state['values']['path'])) < 2) {
+        form_set_error('path', t('Illegal path entered.'));
+    }
+  }  
+}
+
+/**
+ * Handles the creation of a new path by redirecting to 
+ * metatags_quick_admin_path_based_metatags_edit() which autocreates new
+ * entities if they don't exist yet for a given path and language.
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_submit($form, &$form_state) {
+  if(isset($form_state['values']['path'])) {
+    // redirect to existing form
+    $destination = drupal_get_destination();
+    $form_state['redirect'] = array(
+      'admin/config/search/metatags_quick/path_based_metatags/edit',
+      array(
+       'query' => array(
+         'lang' => check_plain($form_state['values']['language']),
+         'path' => check_plain($form_state['values']['path']),
+         'destination' => $destination['destination'])
+       )
+    );
+  }
+}
+
+/**
+ * Displays a form to the user allowing him to edit the path and all the fields
+ * of the metatag entity associated with that path
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_edit($form, $form_state) {
+  $controller = new DrupalDefaultEntityController('metatags_path_based');
+  $entity_id = db_select('metatags_quick_path_based', 'm')
+    ->fields('m', array('id'))
+    ->condition('lang', check_plain($_GET['lang']))
+    ->condition('path', check_plain($_GET['path']))
+    ->execute()
+    ->fetchField();
+  if (!$entity_id) {
+    $entity_id = db_insert('metatags_quick_path_based')
+      ->fields(array('lang' => check_plain($_GET['lang']), 'path' => check_plain($_GET['path'])))
+      ->execute();
+  }
+  $entities = $controller->load(array($entity_id));
+  $form_state['entity'] = $entities[$entity_id];
+  field_attach_form('metatags_path_based', $entities[$entity_id], $form, $form_state);
+  //
+  $form['path'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Edit path'),
+      '#description' => t('Enter path starting without a leading "/". "*" can be used as a wildcard at the end of a path.'),
+      '#default_value' => check_plain($_GET['path']),
+      '#weight' => '-50'
+  );
+  $form['old_path'] = array(
+      '#type' => 'hidden',
+      '#value' => check_plain($_GET['path'])
+  );
+  $form['old_lang'] = array(
+      '#type' => 'hidden',
+      '#value' => check_plain($_GET['lang'])
+  );
+  //
+  $form['submit'] = array(
+    '#value' => t('Submit'),
+    '#type' => 'submit',
+    '#weight' => '49'
+  );
+  $form['cancel'] = array(
+    '#type' => 'submit',
+    '#value' => t('Cancel'),
+    '#weight' => 20,
+    '#submit' => array('metatags_quick_admin_path_based_metatags_edit_cancel'),
+    '#weight' => '50'
+  );
+  return $form;
+}
+
+/**
+ * Returns back to the metatags listing
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_edit_cancel($form, &$form_state) {
+  if(isset($_GET['destination']))
+    $form_state['redirect'] = $_GET['destination'];
+}
+
+/**
+ * Checks if the user has submitted a valid path. Path must be at least 2
+ * characters long
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_edit_validate($form, $form_state) {
+  if(isset($form_state['values']['path'])) {
+    // create path and empty entity
+    if(strlen(trim($form_state['values']['path'])) < 2) {
+        form_set_error('path', t('Illegal path entered.'));
+    }
+  }
+}
+
+/**
+ * Updates the metatags entity for a given path after the user has submitted the
+ * form. Also updates the path if it has been altered.
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_edit_submit($form, $form_state) {
+  // abort if there is no valid entity
+  if (!$form_state['entity']) {
+    form_set_error();
+    drupal_set_message(t('Wrong path'), 'error');
+    return;
+  }
+  // update path if it has been altered
+  if($form_state['values']['path'] != $form_state['values']['old_path']) {
+    // check if there isn't already a path like the new path
+    $entity_id = db_select('metatags_quick_path_based', 'm')
+      ->fields('m', array('id'))
+      ->condition('lang', check_plain($form_state['values']['old_lang']))
+      ->condition('path', check_plain($form_state['values']['path']))
+      ->execute()
+      ->fetchField();
+    // if not continue
+    if(!$entity_id) {
+    db_update('metatags_quick_path_based')
+      ->fields(array(
+        'path' => check_plain(trim($form_state['values']['path'])),
+      ))
+      ->condition('id', $form_state['entity']->id)
+      ->execute();
+    } else {
+      // otherwise abort with error message
+      form_set_error('path', t('Path already exists!'));
+      return;
+    }
+  }
+  // update entity fields
+  $entity = $form_state['entity'];
+  entity_form_submit_build_entity('metatags_path_based', $entity, $form, $form_state);
+  field_attach_update('metatags_path_based', $entity);
+  // display message and redirect
+  drupal_set_message('Meta tags updated', 'status');
+  if(isset($_GET['destination']))
+    $form_state['redirect'] = $_GET['destination'];
+  else 
+    $form_state['redirect'] = FALSE;
+}
+
+/**
+ * Display a delet confirmation for the user allowing him to choose to proceed 
+ * or abort the removal.
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_delete($form, $form_state) {
+  // display delete confirmation
+  if(isset($_GET['path'])) {
+    $form['intro'] = array(
+      '#type' => 'item',
+      '#markup' => t('Do you really want to delete the following path:'),
+    );
+    $form['item'] = array(
+      '#type' => 'item',
+      '#markup' => $_GET['path'],
+      '#prefix' => '<ul><li>',
+      '#suffix' => '</ul></li>'
+    );
+    $form['note'] = array(
+      '#type' => 'item',
+      '#markup' => t('This action cannot be undone.'),
+    );
+    $form['actions'] = array(
+      '#type' => 'actions',
+      'delete' => array(
+        '#type' => 'submit',
+        '#value' => t('Delete'),
+        '#submit' => array('metatags_quick_admin_path_based_metatags_delete_submit')),
+      'cancel' => array(
+        '#type' => 'submit',
+        '#value' => t('Cancel'),
+        '#limit_validation_errors' => array(),
+        '#submit' => array('metatags_quick_admin_path_based_metatags_delete_cancel')));
+    return $form;
+  }
+}
+
+/**
+ * Deletion has been confirmed. Item will be deleted if it is a valid one.
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_delete_submit($form, &$form_state) {
+  // fetch and delete
+  $controller = new DrupalDefaultEntityController('metatags_path_based');
+  $entity_id = db_select('metatags_quick_path_based', 'm')
+    ->fields('m', array('id'))
+    ->condition('lang', check_plain($_GET['lang']))
+    ->condition('path', check_plain($_GET['path']))
+    ->execute()
+    ->fetchField();
+  if (!$entity_id) {
+    drupal_set_message(t('Path not found!'), 'error');
+  } else {
+    metatags_path_based_delete($entity_id);
+  }
+}
+
+/**
+ * Cancels the deletion and should return to the listing
+ *
+ * @param type $form
+ * @param type $form_state
+ */
+function metatags_quick_admin_path_based_metatags_delete_cancel($form, &$form_state) {
+  if(isset($_GET['destination']))
+    $form_state['redirect'] = $_GET['destination'];
+}
+
+/**
+ * creates a select list compatible list of languages keyed by language tags and
+ * with localized language values.
+ *
+ * @global type $language
+ * @return array $languages
+ */
+function _metatags_quick_language_list() {
+  global $language;
+  $languages = array();
+  foreach(language_list() as $lang) {
+    $languages[$lang->language] = t($lang->name);
+  }
+  return $languages;
+}
\ No newline at end of file
diff --git a/metatags_quick.module b/metatags_quick.module
old mode 100644
new mode 100755
index 3fe5e64..f5c8019
--- a/metatags_quick.module
+++ b/metatags_quick.module
@@ -1,432 +1,484 @@
-<?php
-/**
- * @file Quick and dirty implementation of meta tags for drupal 7
- * Module defines new field type 'meta'.
- * Fields of this type are not displayed in HTML.
- * Instead, they add html meta to the head section.
- * 
- * @author Valery L. Lourie <http://drupal.org/user/239562>
- */
-
-/**
- * Implements hook_menu().
- * @see http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_menu/7
- */
-function metatags_quick_menu() {
-  $items['admin/config/search/metatags_quick'] = array(
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('metatags_quick_admin_settings'),
-    'title' => 'Meta tags (quick) settings',
-    'access arguments' => array('administer metatags_quick'),
-    'file' => 'metatags_quick.admin.inc',
-  );
-  $items['admin/config/search/metatags_quick/settings'] = array(
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('metatags_quick_admin_settings'),
-    'title' => 'General',
-    'access arguments' => array('administer metatags_quick'),
-    'file' => 'metatags_quick.admin.inc',
-    'type' => MENU_DEFAULT_LOCAL_TASK,
-  );
-  $items['admin/config/search/metatags_quick/path'] = array(
-    'page callback' => 'metatags_quick_admin_path_page',
-    'title' => 'Edit meta tags',
-    'access arguments' => array('edit metatags_quick'),
-    'file' => 'metatags_quick.admin.inc',
-    'type' => MENU_CALLBACK,
-  );
-
-  $items['admin/config/search/metatags_quick/upgrade'] = array(
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('metatags_quick_upgrade'),
-    'title' => 'Upgrade from nodewords',
-    'access arguments' => array('administer metatags_quick'),
-    'file' => 'nodewords_upgrade.inc',
-    'type' => MENU_LOCAL_TASK,
-  );
-  
-  return $items;
-}
-
-/**
- * Implements hook_permission
- * @see http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_permission/7
- */
-function metatags_quick_permission() {
-  return array(
-    'administer metatags_quick' => array(
-      'title' => t('Administer metatags(quick)'), 
-    ),
-    'edit metatags_quick' => array(
-      'title' => t('Edit meta tags'), 
-    ),
-  );
-}
-
-/**
- * Implements hook_entity_info().
- */
-function metatags_quick_entity_info() {
-  $return = array(
-    'metatags_path_based' => array(
-      'label' => t('Path-based meta tags'),
-      'fieldable' => TRUE,
-      'bundles' => array(
-        'metatags_path_based' => array(
-          'label' => t('Path-based meta tags'),
-          'admin' => array(
-            'path' => 'admin/config/search/metatags_quick',
-            'access arguments' => array('edit metatags_quick'),
-          ),
-        ),
-      ),
-      'base table' => 'metatags_quick_path_based',
-      'entity keys' => array('id' => 'id'),
-    ),
-  );
-  return $return;
-}
-
-/**
- * Implements hook_field_info().
- * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_info/7
- */
-function metatags_quick_field_info() {
-  return array(
-    'metatags_quick' => array(
-      'label' => 'Meta',
-      'description' => t('Meta tag to be displayed in the head section.'),
-      'settings' => array('meta_name',),
-      'default_widget' => 'text_textarea',
-      'default_formatter' => 'metatags_quick_default',
-      'property_type' => 'text',
-    ),
-  );
-}
-
-/**
- * On field load, add meta name to the field data for storage in cache
- * and further rendering
- * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_load/7
- */
-function metatags_quick_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
-  foreach ($items as $lang => $lang_item) {
-    foreach ($lang_item as $i => $final_item) {
-      $items[$lang][$i]['meta_name'] = $field['settings']['meta_name'];  
-    }
-  }
-}
-
-/**
- * Implements hook_field_insert
- * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_insert/7
- */
-function metatags_quick_field_insert($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
-  // Serialize array items - for the meta robots
-  foreach ($items as $index => $item) {
-    if (is_array($item['metatags_quick'])) {
-      $non_empty = array();
-      foreach ($item['metatags_quick'] as $subitem) {
-        if ($subitem) {
-          $non_empty[] = $subitem;
-        }
-      }
-      $items[$index]['metatags_quick'] = join(',', $non_empty);
-    }
-  }
-}
-
-/**
- * Implements hook_field_update
- * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_update/7
- */
-function metatags_quick_field_update($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
-  metatags_quick_field_insert($entity_type, $entities, $field, $instances, $langcode, $items, $age);
-}
-
-
-/**
- * Implements hook_page_build
- */
-function metatags_quick_page_build(&$page) {
-  global $language;
-  if (variable_get('metatags_quick_use_path_based', 0) && _metatags_quick_path_based_page()) {
-    // Try to load path-based meta tags
-    $path_based_id = db_select('metatags_quick_path_based', 'pv')
-      ->condition('lang', $language->language)
-      ->condition('path', $_GET['q'])
-      ->fields('pv', array('id'))
-      ->execute()
-      ->fetchField();
-    if ($path_based_id > 0) {
-      $controller = new DrupalDefaultEntityController('metatags_path_based');
-      $path_entities = $controller->load(array($path_based_id));
-      foreach ($path_entities as $entity) {
-        field_attach_view('metatags_path_based', $entity, 'default');
-      }
-    }
-  }
-}
-
-/**
- * Implements hook_menu_local_tasks_alter().
- */
-function metatags_quick_menu_local_tasks_alter(&$data, $router_item, $root_path) {
-  // Don't add meta tags editing links to admin pages.
-  if (path_is_admin($_GET['q'])) {
-    return;
-  }
-  
-  // Don't add meta tags editing links if path based meta tags are disabled.
-  if (!variable_get('metatags_quick_use_path_based', 1)) {
-    return;
-  }
-  
-  if (!_metatags_quick_path_based_page()) {
-    return;
-  }
-  
-  global $language;
-  $active_item = menu_get_item();
-  $edit_url = 'admin/config/search/metatags_quick/path';
-  $item = menu_get_item($edit_url);
-  if ($item['access']) {
-    $item['#href'] = $edit_url;
-    $item['localized_options']['query'] = array('path' => $_GET['q'], 'lang' => $language->language);
-    $data['tabs'][0]['output'][] = array(
-      '#theme' => 'menu_local_task',
-      '#link' => $item,
-    );
-    if (isset($data['tabs'][0]['count'])) {
-      ++$data['tabs'][0]['count']; 
-    }
-    else {
-      $data['actions'] = array('count' => 0, 'output' => array());
-      // Drupal does not display single tab. WTF?
-      $data['tabs'][0]['count'] = 2;
-    }
-  }
-}
-
-
-/**
- * Implements hook_field_validate().
- *
- */
-function metatags_quick_field_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) {
-  foreach ($items as $delta => $item) {
-    if (!empty($item['metatags_quick']) && !is_array($item['metatags_quick']) && _metatags_strlen($item['metatags_quick']) > 255) {
-      $error = t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => 255));
-      $errors[$field['field_name']][$langcode][$delta][] = array(
-        'error' => $error, 
-        'message' => $error,
-      );
-    }
-  }
-  return;
-}
-
-
-/**
- * Implements hook_content_is_empty().
- */
-function metatags_quick_field_is_empty($item, $field) {
-  if (empty($item['metatags_quick'])) {
-    return TRUE;
-  }
-  return FALSE;
-}
-
-/**
- * Implements hook_field_formatter_info().
- *
- */
-function metatags_quick_field_formatter_info() {
-  $formats = array(
-    'metatags_quick_default' => array(
-      'label' => t('Default metatags_quick link'),
-      'description' => t('Add meta to html head.'),
-      'field types' => array('metatags_quick'),
-    ),
-  );
-  return $formats;
-}
-
-/**
- * Implements hook_field_formatter_view().
- */
-function metatags_quick_field_formatter_view($object_type, $object, $field, $instance, $langcode, $items, $display) {
-  $element = array();
-  switch ($display['type']) {
-    case 'metatags_quick_default':
-      foreach ($items as $delta => $item) {
-        _metatags_quick_add_head(array(
-          'name' => $item['meta_name'],
-          'content' => $item['metatags_quick'],
-        ));        
-      }
-      // Hide element.
-      $element = array('#markup' => '', '#printed' => TRUE);      
-      break;
-
-  }
-  return $element;
-}
-
-/**
- * Implements hook_field_widget_info().
- */
-function metatags_quick_field_widget_info() {
-  return array(
-    'metatags_quick_textarea' => array(
-      'label' => t('Text area'),
-      'field types' => array('metatags_quick'),
-    ),
-    'metatags_quick_textfield' => array(
-      'label' => t('Text field'),
-      'field types' => array('metatags_quick'),
-    ),
-    'metatags_quick_checkboxes' => array(
-      'label' => t('Checkboxes'),
-      'field types' => array('metatags_quick'),
-    ),
-  );
-}
-
-/**
- * Implements hook_field_settings_form().
- */
-function metatags_quick_field_settings_form($field, $instance) {
-  $settings = $field['settings'];
-  
-  if (empty($settings['meta_name'])) {
-    preg_match('/field_(.*)/', $instance['field_name'], $matches);
-    $settings['meta_name'] = $matches[1]; 
-  }
-
-  $form['meta_name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Meta name'),
-    '#default_value' => $settings['meta_name'],
-    '#description' => t('Meta name (defaults to the field name)'),
-    '#required' => TRUE,
-  );
-  
-  return $form;
-}
-
-/**
- * Implements hook_field_instance_settings_form().
- * http://api.drupal.org/api/drupal/modules--field_ui--field_ui.api.php/function/hook_field_instance_settings_form/7
- */
-function metatags_quick_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
-  if ($instance['widget']['type'] == 'metatags_quick_checkboxes') {
-    $form['options'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Possible tags'),
-      '#default_value' => $settings['options'],
-      '#description' => t('Possible values, separated by comma'),
-      '#required' => TRUE,
-    );
-    return $form;
-  }
-}
-
-/**
- * Implements hook_field_widget_form().
- */
-function metatags_quick_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) {
-  $element = $base;
-  switch ($instance['widget']['type']) {
-    case 'metatags_quick_textfield':
-      $addition = array(
-        '#type' => 'textfield',
-        '#maxlength' => 255,
-        '#default_value' => isset($items[$delta]['metatags_quick']) ? $items[$delta]['metatags_quick'] : NULL,
-      );
-      break;
-    case 'metatags_quick_checkboxes':
-      $addition = array(
-        '#type' => 'checkboxes',
-        '#options' => drupal_map_assoc(isset($instance['settings']['options']) ? explode(',', $instance['settings']['options']) : array('noindex', 'nofollow')),
-        '#default_value' => isset($items[$delta]['metatags_quick']) ? explode(',', $items[$delta]['metatags_quick']) : array(),
-      );
-      break;
-    default:
-      $addition = array(
-        '#type' => 'textarea',
-        '#default_value' => isset($items[$delta]['metatags_quick']) ? $items[$delta]['metatags_quick'] : NULL,
-        '#rows' => 5,
-      );
-  }
-  $element['metatags_quick'] = $base + $addition;
-  return $element;
-}
-
-// Private functions area, may change without prior notice.
-
-// Adds meta tag to internal storage that will be processed during page build.
-function _metatags_quick_add_head($item = FALSE) {
-  static $added_meta = array();
-  static $meta_data = array();
-  if (!empty($added_meta[$item['name']])) {
-    return;
-  }
-  // Only output meta if content is not empty.
-  if ($item['content']) {
-    $content = $item['content'];
-    if (!empty($item['type']) && !empty($item['entity'])) {
-      $content = token_replace($content, array(
-        $item['type'] => $item['entity'],
-      ));
-    }
-    else {
-      $content = token_replace($content);
-    }
-    // (Not nice) hack to separate multiple tags returned by token.
-    $content = preg_replace('/<\/a><a/', '<\/a>, <a', $content);
-    $content = trim(strip_tags($content));
-    $item['content'] = $content;
-    $meta_data[] = $item;
-    $element = array(
-      '#tag' => 'meta',
-      '#attributes' => array(
-        'name' => $item['name'],
-        'content' => $item['content'],
-      ),
-    );
-    drupal_add_html_head($element, 'metatags_quick_' . $item['name']);
-    
-  }
-  $added_meta[$item['name']] = TRUE;
-}
-
-// Default settings array
-function _metatags_quick_settings_default() {
-  return array(
-    'use_front' => FALSE,
-    'use_path_based' => FALSE,
-  );
-}
-
-function _metatags_strlen($str) {
-  if (function_exists('mb_strlen')) {
-    return mb_strlen($str, 'UTF-8');
-  }
-  else {
-    return strlen($str);
-  }
-}
-
-/**
- * Determine if current page has to be served by path based
- * (not entity based) meta tags set.
- */
-function _metatags_quick_path_based_page() {
-  $router_item = menu_get_item();
-  // @todo: is there another way to decide?
-  return !is_array($router_item['page_arguments'])
-    || count($router_item['page_arguments']) == 0
-    || !($router_item['page_arguments'][0] instanceof stdClass);
+<?php
+/**
+ * @file Quick and dirty implementation of meta tags for drupal 7
+ * Module defines new field type 'meta'.
+ * Fields of this type are not displayed in HTML.
+ * Instead, they add html meta to the head section.
+ * 
+ * @author Valery L. Lourie <http://drupal.org/user/239562>
+ */
+
+/**
+ * Implements hook_menu().
+ * @see http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_menu/7
+ */
+function metatags_quick_menu() {
+  $items['admin/config/search/metatags_quick'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('metatags_quick_admin_settings'),
+    'title' => 'Meta tags (quick) settings',
+    'access arguments' => array('administer metatags_quick'),
+    'file' => 'metatags_quick.admin.inc',
+  );
+  $items['admin/config/search/metatags_quick/path_based_metatags'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('metatags_quick_admin_path_based_metatags'),
+    'title' => 'Path-Based Metatags',
+    'access arguments' => array('edit metatags_quick'),
+    'file' => 'metatags_quick.admin.inc',
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 50
+  );
+  $items['admin/config/search/metatags_quick/path_based_metatags/edit'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('metatags_quick_admin_path_based_metatags_edit'),
+    'title' => 'Path-Based Metatags',
+    'access arguments' => array('edit metatags_quick'),
+    'file' => 'metatags_quick.admin.inc',
+    'type' => MENU_CALLBACK
+  );
+  $items['admin/config/search/metatags_quick/path_based_metatags/delete'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('metatags_quick_admin_path_based_metatags_delete'),
+    'title' => 'Path-Based Metatags',
+    'access arguments' => array('edit metatags_quick'),
+    'file' => 'metatags_quick.admin.inc',
+    'type' => MENU_CALLBACK
+  );
+  $items['admin/config/search/metatags_quick/settings'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('metatags_quick_admin_settings'),
+    'title' => 'General',
+    'access arguments' => array('administer metatags_quick'),
+    'file' => 'metatags_quick.admin.inc',
+    'type' => MENU_DEFAULT_LOCAL_TASK,
+  );
+  $items['admin/config/search/metatags_quick/path'] = array(
+    'page callback' => 'metatags_quick_admin_path_page',
+    'title' => 'Edit meta tags',
+    'access arguments' => array('edit metatags_quick'),
+    'file' => 'metatags_quick.admin.inc',
+    'type' => MENU_CALLBACK,
+  );
+
+  $items['admin/config/search/metatags_quick/upgrade'] = array(
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('metatags_quick_upgrade'),
+    'title' => 'Upgrade from nodewords',
+    'access arguments' => array('administer metatags_quick'),
+    'file' => 'nodewords_upgrade.inc',
+    'type' => MENU_LOCAL_TASK,
+  );
+  
+  return $items;
+}
+
+/**
+ * Implements hook_permission
+ * @see http://api.drupal.org/api/drupal/modules--system--system.api.php/function/hook_permission/7
+ */
+function metatags_quick_permission() {
+  return array(
+    'administer metatags_quick' => array(
+      'title' => t('Administer metatags(quick)'), 
+    ),
+    'edit metatags_quick' => array(
+      'title' => t('Edit meta tags'), 
+    ),
+  );
+}
+
+/**
+ * Implements hook_entity_info().
+ */
+function metatags_quick_entity_info() {
+  $return = array(
+    'metatags_path_based' => array(
+      'label' => t('Path-based meta tags'),
+      'fieldable' => TRUE,
+      'bundles' => array(
+        'metatags_path_based' => array(
+          'label' => t('Path-based meta tags'),
+          'admin' => array(
+            'path' => 'admin/config/search/metatags_quick',
+            'access arguments' => array('edit metatags_quick'),
+          ),
+        ),
+      ),
+      'base table' => 'metatags_quick_path_based',
+      'entity keys' => array('id' => 'id'),
+    ),
+  );
+  return $return;
+}
+
+/**
+ * Implements hook_field_info().
+ * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_info/7
+ */
+function metatags_quick_field_info() {
+  return array(
+    'metatags_quick' => array(
+      'label' => 'Meta',
+      'description' => t('Meta tag to be displayed in the head section.'),
+      'settings' => array('meta_name',),
+      'default_widget' => 'text_textarea',
+      'default_formatter' => 'metatags_quick_default',
+      'property_type' => 'text',
+    ),
+  );
+}
+
+/**
+ * On field load, add meta name to the field data for storage in cache
+ * and further rendering
+ * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_load/7
+ */
+function metatags_quick_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
+  foreach ($items as $lang => $lang_item) {
+    foreach ($lang_item as $i => $final_item) {
+      $items[$lang][$i]['meta_name'] = $field['settings']['meta_name'];  
+    }
+  }
+}
+
+/**
+ * Implements hook_field_insert
+ * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_insert/7
+ */
+function metatags_quick_field_insert($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
+  // Serialize array items - for the meta robots
+  foreach ($items as $index => $item) {
+    if (is_array($item['metatags_quick'])) {
+      $non_empty = array();
+      foreach ($item['metatags_quick'] as $subitem) {
+        if ($subitem) {
+          $non_empty[] = $subitem;
+        }
+      }
+      $items[$index]['metatags_quick'] = join(',', $non_empty);
+    }
+  }
+}
+
+/**
+ * Implements hook_field_update
+ * @see http://api.drupal.org/api/drupal/modules--field--field.api.php/function/hook_field_update/7
+ */
+function metatags_quick_field_update($entity_type, $entities, $field, $instances, $langcode, &$items, $age) {
+  metatags_quick_field_insert($entity_type, $entities, $field, $instances, $langcode, $items, $age);
+}
+
+
+/**
+ * Implements hook_page_build
+ */
+function metatags_quick_page_build(&$page) {
+  global $language;
+  if (variable_get('metatags_quick_use_path_based', 0) && _metatags_quick_path_based_page()) {
+    // Try to load path-based meta tags
+    $path_based_id = db_select('metatags_quick_path_based', 'pv')
+      ->condition('lang', $language->language)
+      ->condition('path', $_GET['q'])
+      ->fields('pv', array('id'))
+      ->execute()
+      ->fetchField();
+    // if no excact match found - do wildcard search
+    if ($path_based_id == 0 && strstr($_GET['q'], "/")) {
+      $parts = explode("/", $_GET['q']);
+      // iterate through parts
+      for($i = count($parts) - 1; $i > 0; $i--) {
+        // create path
+        $path = "";
+        for($j = 0; $j < $i; $j++) {
+          $path .= $parts[$j] . "/";
+        }
+        // do wildcard query
+        $path_based_id = db_select('metatags_quick_path_based', 'pv')
+          ->condition('lang', $language->language)
+          ->condition('path', $path . "*")
+          ->fields('pv', array('id'))
+          ->execute()
+          ->fetchField();
+        // check for results
+        if($path_based_id > 0) {
+          break;
+        }
+      }
+    }
+    if ($path_based_id > 0) {
+      $controller = new DrupalDefaultEntityController('metatags_path_based');
+      $path_entities = $controller->load(array($path_based_id));
+      foreach ($path_entities as $entity) {
+        field_attach_view('metatags_path_based', $entity, 'default');
+      }
+    }
+  }
+}
+
+/**
+ * Implements hook_menu_local_tasks_alter().
+ */
+function metatags_quick_menu_local_tasks_alter(&$data, $router_item, $root_path) {
+  // Don't add meta tags editing links to admin pages.
+  if (path_is_admin($_GET['q'])) {
+    return;
+  }
+  
+  // Don't add meta tags editing links if path based meta tags are disabled.
+  if (!variable_get('metatags_quick_use_path_based', 0)) {
+    return;
+  }
+  
+  if (!_metatags_quick_path_based_page()) {
+    return;
+  }
+  
+  global $language;
+  $active_item = menu_get_item();
+  $edit_url = 'admin/config/search/metatags_quick/path';
+  $item = menu_get_item($edit_url);
+  if ($item['access']) {
+    $item['#href'] = $edit_url;
+    $item['localized_options']['query'] = array('path' => $_GET['q'], 'lang' => $language->language);
+    $data['tabs'][0]['output'][] = array(
+      '#theme' => 'menu_local_task',
+      '#link' => $item,
+    );
+    if (isset($data['tabs'][0]['count'])) {
+      ++$data['tabs'][0]['count']; 
+    }
+    else {
+      $data['actions'] = array('count' => 0, 'output' => array());
+      // Drupal does not display single tab. WTF?
+      $data['tabs'][0]['count'] = 2;
+    }
+  }
+}
+
+
+/**
+ * Implements hook_field_validate().
+ *
+ */
+function metatags_quick_field_validate($obj_type, $object, $field, $instance, $langcode, $items, &$errors) {
+  foreach ($items as $delta => $item) {
+    if (!empty($item['metatags_quick']) && !is_array($item['metatags_quick']) && _metatags_strlen($item['metatags_quick']) > 255) {
+      $error = t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => 255));
+      $errors[$field['field_name']][$langcode][$delta][] = array(
+        'error' => $error, 
+        'message' => $error,
+      );
+    }
+  }
+  return;
+}
+
+
+/**
+ * Implements hook_content_is_empty().
+ */
+function metatags_quick_field_is_empty($item, $field) {
+  if (empty($item['metatags_quick'])) {
+    return TRUE;
+  }
+  return FALSE;
+}
+
+/**
+ * Implements hook_field_formatter_info().
+ *
+ */
+function metatags_quick_field_formatter_info() {
+  $formats = array(
+    'metatags_quick_default' => array(
+      'label' => t('Default metatags_quick link'),
+      'description' => t('Add meta to html head.'),
+      'field types' => array('metatags_quick'),
+    ),
+  );
+  return $formats;
+}
+
+/**
+ * Implements hook_field_formatter_view().
+ */
+function metatags_quick_field_formatter_view($object_type, $object, $field, $instance, $langcode, $items, $display) {
+  $element = array();
+  switch ($display['type']) {
+    case 'metatags_quick_default':
+      foreach ($items as $delta => $item) {
+        _metatags_quick_add_head(array(
+          'name' => $item['meta_name'],
+          'content' => $item['metatags_quick'],
+        ));        
+      }
+      // Hide element.
+      $element = array('#markup' => '', '#printed' => TRUE);      
+      break;
+
+  }
+  return $element;
+}
+
+/**
+ * Implements hook_field_widget_info().
+ */
+function metatags_quick_field_widget_info() {
+  return array(
+    'metatags_quick_textarea' => array(
+      'label' => t('Text area'),
+      'field types' => array('metatags_quick'),
+    ),
+    'metatags_quick_textfield' => array(
+      'label' => t('Text field'),
+      'field types' => array('metatags_quick'),
+    ),
+    'metatags_quick_checkboxes' => array(
+      'label' => t('Checkboxes'),
+      'field types' => array('metatags_quick'),
+    ),
+  );
+}
+
+/**
+ * Implements hook_field_settings_form().
+ */
+function metatags_quick_field_settings_form($field, $instance) {
+  $settings = $field['settings'];
+  
+  if (empty($settings['meta_name'])) {
+    preg_match('/field_(.*)/', $instance['field_name'], $matches);
+    $settings['meta_name'] = $matches[1]; 
+  }
+
+  $form['meta_name'] = array(
+    '#type' => 'textfield',
+    '#title' => t('Meta name'),
+    '#default_value' => $settings['meta_name'],
+    '#description' => t('Meta name (defaults to the field name)'),
+    '#required' => TRUE,
+  );
+  return $form;
+}
+
+/**
+ * Implements hook_field_widget_form().
+ */
+function metatags_quick_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $base) {
+  $element = $base;
+  switch ($instance['widget']['type']) {
+    case 'metatags_quick_textfield':
+      $addition = array(
+        '#type' => 'textfield',
+        '#maxlength' => 255,
+        '#default_value' => isset($items[$delta]['metatags_quick']) ? $items[$delta]['metatags_quick'] : NULL,
+      );
+      break;
+    case 'metatags_quick_checkboxes':
+      $addition = array(
+        '#type' => 'checkboxes',
+        '#options' => drupal_map_assoc(array('noindex', 'nofollow')),
+        '#default_value' => isset($items[$delta]['metatags_quick']) ? explode(',', $items[$delta]['metatags_quick']) : array(),
+      );
+      break;
+    default:
+      $addition = array(
+        '#type' => 'textarea',
+        '#default_value' => isset($items[$delta]['metatags_quick']) ? $items[$delta]['metatags_quick'] : NULL,
+        '#rows' => 5,
+      );
+  }
+  $element['metatags_quick'] = $base + $addition;
+  return $element;
+}
+
+// Private functions area, may change without prior notice.
+
+// Adds meta tag to internal storage that will be processed during page build.
+function _metatags_quick_add_head($item = FALSE) {
+  static $added_meta = array();
+  static $meta_data = array();
+  if (!empty($added_meta[$item['name']])) {
+    return;
+  }
+  // Only output meta if content is not empty.
+  if ($item['content']) {
+    $content = $item['content'];
+    if (!empty($item['type']) && !empty($item['entity'])) {
+      $content = token_replace($content, array(
+        $item['type'] => $item['entity'],
+      ));
+    }
+    else {
+      $content = token_replace($content);
+    }
+    // (Not nice) hack to separate multiple tags returned by token.
+    $content = preg_replace('/<\/a><a/', '<\/a>, <a', $content);
+    $content = trim(strip_tags($content));
+    $item['content'] = $content;
+    $meta_data[] = $item;
+    $element = array(
+      '#tag' => 'meta',
+      '#attributes' => array(
+        'name' => $item['name'],
+        'content' => $item['content'],
+      ),
+    );
+    drupal_add_html_head($element, 'metatags_quick_' . $item['name']);
+    
+  }
+  $added_meta[$item['name']] = TRUE;
+}
+
+// Default settings array
+function _metatags_quick_settings_default() {
+  return array(
+    'use_front' => FALSE,
+    'use_path_based' => FALSE,
+  );
+}
+
+function _metatags_strlen($str) {
+  if (function_exists('mb_strlen')) {
+    return mb_strlen($str, 'UTF-8');
+  }
+  else {
+    return strlen($str);
+  }
+}
+
+/**
+ * Determine if current page has to be served by path based
+ * (not entity based) meta tags set.
+ */
+function _metatags_quick_path_based_page() {
+  $router_item = menu_get_item();
+  // @todo: is there another way to decide?
+  return !is_array($router_item['page_arguments'])
+    || count($router_item['page_arguments']) == 0
+    || !($router_item['page_arguments'][0] instanceof stdClass);
+}
+
+function metatags_path_based_delete($entity) {
+  if(!is_object($entity)) {
+    $controller = new DrupalDefaultEntityController('metatags_path_based');
+    $entity = db_select('metatags_quick_path_based', 'm')
+      ->fields('m', array('id'))
+      ->condition('id', (int)$entity)
+      ->execute()
+      ->fetchField();
+    if($entity)
+      $entity = array_pop(array_values(entity_load('metatags_path_based', array($entity))));
+  }
+  if(!$entity || !is_object($entity) || !isset($entity->path))
+    return false;
+  // do the deletion
+  field_attach_delete('metatags_path_based', $entity);
+  db_delete('metatags_quick_path_based')
+    ->condition('id', $entity->id)
+    ->condition('path', $entity->path)
+    ->condition('lang', $entity->lang)
+    ->execute();
+  drupal_set_message(t('Path "'.$entity->path.'" and metatags deleted'), 'status');
 }
\ No newline at end of file
