Просмотр исходного кода

Improved blast submission process.

Lacey Sanderson 8 лет назад
Родитель
Сommit
434279e7a4

+ 40 - 9
api/blast_ui.api.inc

@@ -185,23 +185,50 @@ function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $op
   // Strip the extension off the BLAST target
   $database = preg_replace("/(.*)\.[pn]\w\w/", '$1', $database);
 
-  // The executables:
+  // The Blast executeable.
   $program = $blast_path . $program;
+  if (!file_exists($program)) {
+    tripal_report_error(
+      'blast_ui',
+      TRIPAL_ERROR,
+      "Unable to find the BLAST executable (ie: /urs/bin/blastn). This can be changed in the admin settings; you supplied: @command",
+      array('@command' => $program),
+      array('print' => TRUE)
+    );
+    return FALSE;
+  }
+
+  // The blast db formatter executable.
   $blast_formatter_command = $blast_path . 'blast_formatter';
+  if (!file_exists($blast_formatter_command)) {
+    tripal_report_error(
+      'blast_ui',
+      TRIPAL_ERROR,
+      "Unable to find the BLAST Formatter executable (ie: /urs/bin/blast_formatter). This can be changed in the admin settings; you supplied: @command",
+      array('@command' => $blast_formatter_command),
+      array('print' => TRUE)
+    );
+    return FALSE;
+  }
 
-  $blast_cmd = "$program -query '$query' -db '$database' -out '$output_file' -outfmt=11";
+  // Note: all variables are escaped (adds single quotes around their values) for security reasons.
+  $blast_cmd = escapeshellarg($program) . ' -query ' . escapeshellarg($query) . ' -db ' . escapeshellarg($database) . ' -out ' . escapeshellarg($output_file) . ' -outfmt=11';
   if (!empty($options)) {
     foreach ($options as $opt => $val) {
       $val = trim($val);
       if (!empty($val)) {
         print "\t$opt: $val\n";
-        $blast_cmd .= " -$opt $val";
+        // We want to escape all the option values since they were supplied via
+        // user input. These values should also have been checked in the
+        // advanced form _validate functions but this adds an extra layer of
+        // protection.
+        $blast_cmd .= ' -' . escapeshellarg($opt) . ' ' . escapeshellarg($val);
       }
     }
   }
 
  // Setting the value of threads by admin page
- $blast_cmd .= " -num_threads ".$blast_threads;
+ $blast_cmd .= ' -num_threads ' . escapeshellarg($blast_threads);
 
   print "\nExecuting the following BLAST command:\n" . $blast_cmd . "\n";
 
@@ -221,8 +248,8 @@ function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $op
   print "\nGenerating additional download formats...\n";
 
   print "\tXML\n";
-  $format_cmd = "$blast_formatter_command -archive $output_file -outfmt 5 -out $output_file_xml";
-  print "\nExecuting $format_cmd\n\n";
+  $format_cmd = escapeshellarg($blast_formatter_command) . ' -archive ' . escapeshellarg($output_file) . ' -outfmt 5 -out ' . escapeshellarg($output_file_xml);
+  print "\t\tExecuting $format_cmd\n\n";
   system($format_cmd);
   if (!file_exists($output_file_xml)) {
     tripal_report_error(
@@ -235,7 +262,9 @@ function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $op
   }
 
   print "\tTab-delimited\n";
-  system("$blast_formatter_command -archive $output_file -outfmt 7 -out $output_file_tsv");
+  $format_cmd = escapeshellarg($blast_formatter_command) . ' -archive ' . escapeshellarg($output_file) . ' -outfmt 7 -out ' . escapeshellarg($output_file_tsv);
+  print "\t\tExecuting $format_cmd\n\n";
+  system($format_cmd);
   if (!file_exists($output_file_tsv)) {
     tripal_report_error(
       'blast_ui',
@@ -260,7 +289,9 @@ function run_BLAST_tripal_job($program, $query, $database, $output_filestub, $op
   }
 
   print "\tHTML (includes alignments)\n";
-  system("$blast_formatter_command -archive $output_file -outfmt 0 -out $output_file_html -html");
+  $format_cmd = escapeshellarg($blast_formatter_command) . ' -archive ' . escapeshellarg($output_file) . ' -outfmt 0 -out ' . escapeshellarg($output_file_html) . ' -html';
+  print "\t\tExecuting $format_cmd\n\n";
+  system($format_cmd);
   if (!file_exists($output_file_tsv)) {
     tripal_report_error(
       'blast_ui',
@@ -424,7 +455,7 @@ function get_number_of_recent_jobs() {
 function format_query_headers($file) {
 
   $headers = array();
-  exec('grep ">" '.$file, $headers);
+  exec('grep ">" ' . escapeshellarg($file), $headers);
 
   // Easiest case: if there is only one query header then show it.
   if (sizeof($headers) == 1 AND isset($headers[0])) {

+ 70 - 4
includes/blast_ui.form_advanced_options.inc

@@ -116,7 +116,24 @@ function blast_ui_blastn_advanced_options_form(&$form, $form_state) {
  *
  * @see blast_ui_blastn_advanced_options_form().
  */
-function blast_ui_blastn_advanced_options_form_validate($form, $form_state) { }
+function blast_ui_blastn_advanced_options_form_validate($form, $form_state) {
+
+  // Ensure that our textfields are what we expect them to be since we will
+  // use them to generate the BLAST command.
+  // First up, e-value. We expect the evalue to be a very small yet still
+  // positive number. It may be given in scientific notation which is
+  // luckily supported by is_numeric().
+  if (!is_numeric($form_state['values']['eVal'])) {
+    form_set_error('eVal', 'The e-value should be a very small number (scientific notation is supported). For example, <em>0.001</em> or, even better, <em>1e-10</em>.');
+  }
+
+  // Next textfield up, "Max matches in a query range" which is also expected
+  // to be a positive number.
+  if (!is_numeric($form_state['values']['qRange'])) {
+    form_set_error('qRange', 'The "Max matches in a query range" should be a positive integer.');
+  }
+
+}
 
 /**
  * Processed the advanced options provided by the BLASTn form above.
@@ -274,7 +291,24 @@ function blast_ui_blastx_advanced_options_form(&$form, $form_state) {
  *
  * @see blast_ui_blastx_advanced_options_form().
  */
-function blast_ui_blastx_advanced_options_form_validate($form, $form_state) { }
+function blast_ui_blastx_advanced_options_form_validate($form, $form_state) {
+
+  // Ensure that our textfields are what we expect them to be since we will
+  // use them to generate the BLAST command.
+  // First up, e-value. We expect the evalue to be a very small yet still
+  // positive number. It may be given in scientific notation which is
+  // luckily supported by is_numeric().
+  if (!is_numeric($form_state['values']['eVal'])) {
+    form_set_error('eVal', 'The e-value should be a very small number (scientific notation is supported). For example, <em>0.001</em> or, even better, <em>1e-10</em>.');
+  }
+
+  // Next textfield up, "Max matches in a query range" which is also expected
+  // to be a positive number.
+  if (!is_numeric($form_state['values']['qRange'])) {
+    form_set_error('qRange', 'The "Max matches in a query range" should be a positive integer.');
+  }
+
+}
 
 /**
  * Processed the advanced options provided by the BLASTx form above.
@@ -422,7 +456,23 @@ function blast_ui_blastp_advanced_options_form(&$form, $form_state) {
  *
  * @see blast_ui_blastp_advanced_options_form().
  */
-function blast_ui_blastp_advanced_options_form_validate($form, $form_state) { }
+function blast_ui_blastp_advanced_options_form_validate($form, $form_state) {
+
+  // Ensure that our textfields are what we expect them to be since we will
+  // use them to generate the BLAST command.
+  // First up, e-value. We expect the evalue to be a very small yet still
+  // positive number. It may be given in scientific notation which is
+  // luckily supported by is_numeric().
+  if (!is_numeric($form_state['values']['eVal'])) {
+    form_set_error('eVal', 'The e-value should be a very small number (scientific notation is supported). For example, <em>0.001</em> or, even better, <em>1e-10</em>.');
+  }
+
+  // Next textfield up, "Max matches in a query range" which is also expected
+  // to be a positive number.
+  if (!is_numeric($form_state['values']['qRange'])) {
+    form_set_error('qRange', 'The "Max matches in a query range" should be a positive integer.');
+  }
+}
 
 /**
  * Processed the advanced options provided by the BLASTp form above.
@@ -1065,7 +1115,23 @@ function blast_ui_tblastn_advanced_options_form(&$form, $form_state) {
  *
  * @see blast_ui_tblastn_advanced_options_form().
  */
-function blast_ui_tblastn_advanced_options_form_validate($form, $form_state) { }
+function blast_ui_tblastn_advanced_options_form_validate($form, $form_state) {
+
+  // Ensure that our textfields are what we expect them to be since we will
+  // use them to generate the BLAST command.
+  // First up, e-value. We expect the evalue to be a very small yet still
+  // positive number. It may be given in scientific notation which is
+  // luckily supported by is_numeric().
+  if (!is_numeric($form_state['values']['eVal'])) {
+    form_set_error('eVal', 'The e-value should be a very small number (scientific notation is supported). For example, <em>0.001</em> or, even better, <em>1e-10</em>.');
+  }
+
+  // Next textfield up, "Max matches in a query range" which is also expected
+  // to be a positive number.
+  if (!is_numeric($form_state['values']['qRange'])) {
+    form_set_error('qRange', 'The "Max matches in a query range" should be a positive integer.');
+  }
+}
 
 /**
  * Processed the advanced options provided by the tBLASTn form above.

+ 1 - 1
includes/blast_ui.form_per_program.inc

@@ -433,7 +433,7 @@ function blast_ui_per_blast_program_form_submit($form, &$form_state) {
     // to provide multiple download type options from the same BLAST
     $blastdb_with_path = $form_state['upDB_path'];
     $result = NULL;
-    exec("makeblastdb -in $blastdb_with_path -dbtype $mdb_type -parse_seqids 2>&1", $result);
+    exec('makeblastdb -in ' . escapeshellarg($blastdb_with_path) . ' -dbtype ' . escapeshellarg($mdb_type) . ' -parse_seqids 2>&1', $result);
 
     // Check that the BLAST database was made correctly.
     $result = implode('<br />', $result);

+ 1 - 1
theme/blast_ui.theme.inc

@@ -55,7 +55,7 @@ function blast_ui_preprocess_show_blast_report(&$vars) {
   $full_path_xml = DRUPAL_ROOT . DIRECTORY_SEPARATOR . $vars['blast_job']->files->result->xml;
   if (is_readable($full_path_xml)) {
 
-    $vars['num_results'] = `grep -c "<Hit>" $full_path_xml`;
+    $vars['num_results'] = shell_exec('grep -c "<Hit>" ' . escapeshellarg($full_path_xml));
 
     if ($vars['num_results'] < 500) {
       $vars['xml'] = simplexml_load_file($full_path_xml);