 alias/hosting_alias.module   |  5 +--
 client/hosting_client.module | 88 ++++++++++++++++++++++++++++++++++++++++++++
 site/hosting_site.form.inc   |  3 +-
 site/hosting_site.module     | 20 +++++-----
 4 files changed, 103 insertions(+), 13 deletions(-)

diff --git a/alias/hosting_alias.module b/alias/hosting_alias.module
index 0211f20..4b1dd8b 100644
--- a/alias/hosting_alias.module
+++ b/alias/hosting_alias.module
@@ -72,7 +72,7 @@ function hosting_alias_form_site_node_form_alter(&$form, &$form_state) {
 function hosting_alias_site_form_validate($form, &$form_state) {
   $aliases = $form_state['values']['aliases'] = array_filter($form_state['values']['aliases']);
   foreach ($aliases as $key => $alias) {
-    hosting_alias_validate_alias($form_state['node'], $alias, $key);
+    hosting_alias_validate_alias($form_state['values'], $alias, $key);
   }
 }
 
@@ -365,8 +365,7 @@ function hosting_alias_node_revision_delete($node) {
 function hosting_alias_validate_alias($site, $alias, $key) {
   if ($alias = strtolower(trim($alias))) {
     $alias = strtolower(trim($alias));
-    $params = isset($site->nid) ? array('nid' => $site->nid) : array();
-    if (!hosting_domain_allowed($alias, $params) || $alias == $site->title) {
+    if (!hosting_domain_allowed($alias, (array) $site) || $alias == $site->title) {
       form_set_error("aliases][$key", t('The domain name @alias is already in use', array('@alias' => $alias)));
     }
     if (!_hosting_valid_fqdn_wildcard($alias)) {
diff --git a/client/hosting_client.module b/client/hosting_client.module
index 6261029..f5b14e3 100644
--- a/client/hosting_client.module
+++ b/client/hosting_client.module
@@ -88,6 +88,10 @@ function hosting_client_permission() {
     'edit client uname' => array(
       'title' => t('edit client uname'),
     ),
+    'bypass domain owner check' => array(
+      'title' => t('bypass domain owner check'),
+      'description' => t('Allows the client to register a subdomain, even when the above domain is owned by another client.'),
+    ),
   );
 }
 
@@ -1006,6 +1010,12 @@ function hosting_client_configure($form, &$form_state) {
     '#description' => t('If this setting is on, any new client nodes will automatically have a system user account generated for them, and associated with the new client node. Users going through the signup form module have a user created regardless of this setting.'),
     '#default_value' => variable_get('hosting_client_register_user', FALSE),
   );
+  $form['hosting_client_subdomain_owner_check'] = array(
+    '#type' => 'checkbox',
+    '#title' => t('Check owner upon creating subdomains.'),
+    '#description' => t("As a policy a hosting_client user is not allowed to create a site on a domain or subdomain thereof that is already in use by another client. (Unles the client has the 'bypass domain owner check' permission)"),
+    '#default_value' => variable_get('hosting_client_subdomain_owner_check', FALSE),
+  );
 
   // User e-mail settings.
   $form['email'] = array(
@@ -1190,3 +1200,81 @@ function hosting_client_views_api() {
     'path' => drupal_get_path('module', 'hosting_client') . '/includes/views',
   );
 }
+
+/**
+ * Implements hook_allow_domain().
+ *
+ * Disallow domains already used as any site's title/url, unless the site has
+ * been deleted.
+ *
+ * @see hosting_domain_allowed()
+ */
+function hosting_client_allow_domain($url, $params = array()) {
+  // If we do not have to be here, leave ASAP.
+  if (!variable_get('hosting_client_subdomain_owner_check', FALSE) || user_access('bypass domain owner check')) {
+    return TRUE;
+  }
+
+  // Get the client node from the client name.
+  $client = hosting_get_client($params['client']);
+
+  // Prepare array.
+  $subdomains = array();
+
+  // Break up url.
+  $url_array = explode('.', $url);
+  while ($url_array) {
+    $subdomains[] = implode('.', $url_array);
+    array_shift($url_array);
+  }
+
+  // Start query
+  $query = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->condition('n.type', 'site');
+  $query->leftJoin('hosting_site', 'h', 'h.nid = n.nid');
+  $query->condition('h.status', HOSTING_SITE_DELETED, '<>');
+
+  // Check for either ...
+  $or = db_or();
+
+  $sites = db_or();
+  $aliases = db_or();
+
+  // Iterate over all subdomains and populate sites and aliases checks.
+  foreach ($subdomains as $domain) {
+    // Regular site names
+    $sites->condition('n.title', $domain);
+
+    // And aliases
+    $aliases->condition('a.alias', $domain);
+  }
+
+  // Any of the above domains that do not belong to this client.
+  $or->condition(
+    db_and()
+      ->condition($sites)
+      ->condition('h.client', $client->nid, '<>')
+  );
+
+  if (module_exists('hosting_alias')) {
+    $query->leftJoin('hosting_site_alias', 'a', 'n.vid = a.vid');
+
+    // Any of the above domain aliases that do not belong to this client.
+    $or->condition(
+      db_and()
+        ->condition($aliases)
+        ->condition('h.client', $client->nid, '<>')
+    );
+  }
+
+  // Add conditions to the query.
+  $query->condition($or);
+
+  // For existing sites, don't match the site's current url.
+  if (isset($params['nid'])) {
+    $query->condition('n.nid', $params['nid'], '<>');
+  }
+
+  return !$query->countQuery()->execute()->fetchField();
+}
diff --git a/site/hosting_site.form.inc b/site/hosting_site.form.inc
index fc383e9..f87082b 100644
--- a/site/hosting_site.form.inc
+++ b/site/hosting_site.form.inc
@@ -391,8 +391,9 @@ function hosting_site_validate($node, &$form) {
   }
 
   // TODO: maybe we should allow creation of sites that conflict with HOSTING_SITE_DISABLED (which would then need to be renamed before being re-enabled)
+  // TODO: This error is also triggered when the user attempts to register a subdomain of a used site. Perhaps we should read the error code and split the errors?
   if (!hosting_domain_allowed($url, (array) $node)) {
-    form_set_error('title', t("The domain name you have specified is already in use."));
+    form_set_error('title', t("The domain name you have specified is already in use, or does not belong to you."));
   }
 
   // If the quota module is loaded and this is a new node, check
diff --git a/site/hosting_site.module b/site/hosting_site.module
index 38a9175..8fbefbd 100644
--- a/site/hosting_site.module
+++ b/site/hosting_site.module
@@ -661,18 +661,20 @@ function hosting_site_status_codes($type = NULL) {
  * @see hosting_domain_allowed()
  */
 function hosting_site_allow_domain($url, $params = array()) {
-  $query = "SELECT COUNT(n.nid) FROM {node} n
-    JOIN {hosting_site} h ON n.nid = h.nid
-    WHERE type = 'site' AND n.title = :title AND h.status <> :status";
-  $args[':title'] = $url;
-  $args[':status'] = HOSTING_SITE_DELETED;
+  $query = db_select('node', 'n')
+    ->fields('n', array('nid'))
+    ->condition('n.type', 'site')
+    ->condition('n.title', $url);
+
+  $query->leftJoin('hosting_site', 'h', 'h.nid = n.nid');
+  $query->condition('h.status', HOSTING_SITE_DELETED, '<>');
 
+  // For existing sites, don't match the site's current url.
   if (isset($params['nid'])) {
-    $query .= " AND n.nid <> :nid";
-    $args[':nid'] = $params['nid'];
+    $query->condition('n.nid', $params['nid'], '<>');
   }
-  $result = !db_query($query, $args)->fetchField();
-  return $result;
+
+  return !$query->countQuery()->execute()->fetchField();
 }
 
 /**
