Index: server/pifr_server.xmlrpc.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/project_issue_file_review/server/pifr_server.xmlrpc.inc,v
retrieving revision 1.40
diff -u -r1.40 pifr_server.xmlrpc.inc
--- server/pifr_server.xmlrpc.inc	26 Jan 2010 05:40:05 -0000	1.40
+++ server/pifr_server.xmlrpc.inc	5 Feb 2010 06:44:44 -0000
@@ -79,6 +79,13 @@
       );
     }
 
+    if (!($batch = pifr_server_xmlrpc_validate('queue', $batch))) {
+      return array(
+        'response' => PIFR_RESPONSE_DENIED,
+        'errors' => pifr_server_xmlrpc_error(),
+      );
+    }
+
     // Store project data and retrieve completed project information.
     $projects = pifr_server_xmlrpc_project_save($batch['projects'], $client['client_id']);
 
@@ -476,3 +483,180 @@
   $offset = $now - $timestamp;
   return gmmktime() - $offset;
 }
+
+function pifr_server_xmlrpc_validate($method) {
+  $args = func_get_args();
+  array_shift($args);
+
+  $return = call_user_func_array('pifr_server_xmlrpc_validate_' . $method, $args);
+
+  if (pifr_server_xmlrpc_error()) {
+    return FALSE;
+  }
+  return $return;
+}
+
+function pifr_server_xmlrpc_validate_queue(array $batch) {
+  // Ensure every base key is present.
+  $default = array(
+    'branches' => array(),
+    'files' => array(),
+    'projects' => array(),
+  );
+  $batch += $default;
+
+  if (count(array_keys($batch)) > 3) {
+    pifr_server_xmlrpc_error('Only keys [branches, files, projects] are allowed.');
+    pifr_server_xmlrpc_error(print_r($batch, TRUE));
+  }
+
+  // Get a list of supported vcs backends.
+  $includes = file_scan_directory(drupal_get_path('module', 'pifr_client') . '/review/vcs', '.*');
+  $backends = array();
+  foreach ($includes as $include) {
+    $backend = str_replace('.inc', '', $include->basename);
+    if ($backend != 'vcs') {
+      $backends[] = $backend;
+    }
+  }
+
+  // Validate each project.
+  $required_keys = array('client_identifier', 'name', 'repository_type', 'repository_url');
+  $i = 1;
+  $project_identifiers = array();
+  foreach ($batch['projects'] as &$project) {
+    // Ensure that all required keys are found.
+    if ($errors = pifr_server_xmlrpc_required_check($project, $required_keys)) {
+      pifr_server_xmlrpc_error_list('project', $i, $errors);
+      continue;
+    }
+
+    if (!pifr_server_xmlrpc_is_int($project['client_identifier'])) {
+      $errors[] = t('[client_identifier] must be an integer');
+    }
+    elseif (in_array($project['client_identifier'], $project_identifiers)) {
+      $errors[] = t('[client_identifier] must be unique');
+    }
+    if (!in_array($project['repository_type'], $backends)) {
+      $errors[] = t('[repository_type] must be one of [@list]', array('@list' => implode(', ', $backends)));
+    }
+
+    // Keep a list of project identifiers for validation.
+    $project_identifiers[] = $project['client_identifier'];
+
+    // If any errors where found then register an error for the file.
+    pifr_server_xmlrpc_error_list('project', $i, $errors);
+
+    $i++;
+  }
+
+  // Validate each branch.
+  $required_keys = array('project_identifier', 'client_identifier', 'vcs_identifier');
+  $default = array(
+    'dependency' => '',
+    'plugin_argument' => array(),
+    'test' => FALSE,
+  );
+  $i = 1;
+  $branch_identifiers = array();
+  foreach ($batch['branches'] as &$branch) {
+    // Ensure that all required keys are found.
+    if ($errors = pifr_server_xmlrpc_required_check($branch, $required_keys)) {
+      pifr_server_xmlrpc_error_list('branch', $i, $errors);
+      continue;
+    }
+
+    // Provide default values for optional keys.
+    $branch += $default;
+
+    // Validate fields.
+    if (!pifr_server_xmlrpc_is_int($branch['project_identifier'])) {
+      $errors[] = t('[project_identifier] must be an integer');
+    }
+    if (!pifr_server_xmlrpc_is_int($branch['client_identifier'])) {
+      $errors[] = t('[client_identifier] must be an integer');
+    }
+    elseif (in_array($branch['client_identifier'], $branch_identifiers)) {
+      $errors[] = t('[client_identifier] must be unique');
+    }
+    if (!empty($branch['dependency'])) {
+      $dependencies = explode(',', $branch['dependency']);
+      foreach ($dependencies as $dependency) {
+        if (!pifr_server_xmlrpc_is_int($dependency)) {
+          $errors[] = t('all dependencies must be integers');
+          break;
+        }
+      }
+    }
+
+    // Keep a list of branch identifiers for validation.
+    $branch_identifiers[] = $branch['client_identifier'];
+
+    // If any errors where found then register an error for the branch.
+    pifr_server_xmlrpc_error_list('branch', $i, $errors);
+
+    $i++;
+  }
+
+  // Validate each file.
+  $required_keys = array('branch_identifier', 'client_identifier', 'file_url');
+  $i = 1;
+  foreach ($batch['files'] as &$file) {
+    // Ensure that all required keys are found.
+    if ($errors = pifr_server_xmlrpc_required_check($file, $required_keys)) {
+      pifr_server_xmlrpc_error_list('file', $i, $errors);
+      continue;
+    }
+
+    if (!pifr_server_xmlrpc_is_int($file['branch_identifier'])) {
+      $errors[] = t('[branch_identifier] must be an integer');
+    }
+    if (!in_array($file['branch_identifier'], $branch_identifiers)) {
+      $errors[] = t('[branch_identifier] not found in branch list');
+    }
+    if (!pifr_server_xmlrpc_is_int($file['client_identifier'])) {
+      $errors[] = t('[client_identifier] must be an integer');
+    }
+
+    // If any errors where found then register an error for the file.
+    pifr_server_xmlrpc_error_list('file', $i, $errors);
+
+    $i++;
+  }
+
+  pifr_server_xmlrpc_error('ur a n00b');
+  return $batch;
+}
+
+function pifr_server_xmlrpc_error($error = NULL) {
+  static $errors = array();
+
+  if ($error) {
+    $errors[] = $error;
+  }
+  return $errors;
+}
+
+function pifr_server_xmlrpc_error_list($key, $number, array $errors) {
+  if ($errors) {
+    pifr_server_xmlrpc_error(t('Error(s) found in @key #@number: !list.', array(
+      '@key' => $key,
+      '@number' => $number,
+      '!list' => implode(', ', $errors),
+    )));
+  }
+}
+
+function pifr_server_xmlrpc_required_check(array $data, array $required_keys) {
+  $errors = array();
+  foreach ($required_keys as $required_key) {
+    if (empty($data[$required_key])) {
+      $errors[] = t('required key [@key] not found', array('@key' => $required_key));
+    }
+  }
+  return $errors;
+}
+
+function pifr_server_xmlrpc_is_int($value) {
+  return is_numeric($value) && (int) $value == (float) $value;
+}
