Przeglądaj źródła

Redid the job_id encoding to make the URLs prettier while still obfuscating it so researchers are not tempted to look at blast results not their own...

Lacey Sanderson 9 lat temu
rodzic
commit
402bb1f00d

+ 2 - 2
blast_ui.module

@@ -214,12 +214,12 @@ function blast_ui_help($path, $arg) {
  *  Return HTML output of the BLAST results to be displayed to the user
  *
  */
-function show_blast_output($job_id) {
+function show_blast_output($job_string) {
 
   // BLASTs are run as a Tripal job. As such we need to determine whether the current
   // BLAST is in the queue, running or complete in order to determine what to show the user
   //decode the job_id
-  $job_id = base64_decode($job_id);
+  $job_id = blast_ui_reveal_secret($job_string);
   $job = tripal_get_job($job_id);
 
   // 1) Job is in the Queue

+ 4 - 4
includes/blast_ui.form_advanced_options.inc

@@ -25,7 +25,7 @@
 function blast_ui_blastn_advanced_options_form(&$form, $form_state) {
   $all_job_data = variable_get('job_data', '');
   if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = base64_decode($_GET['jid']);
+     $jid = blast_ui_reveal_secret($_GET['jid']);
      $job_data = $all_job_data[$jid];
   }
   else {
@@ -173,7 +173,7 @@ function blast_ui_blastn_advanced_options_form_submit($form, $form_state) {
 function blast_ui_blastx_advanced_options_form(&$form, $form_state) {
   $all_job_data = variable_get('job_data', '');
   if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = base64_decode($_GET['jid']);
+     $jid = blast_ui_reveal_secret($_GET['jid']);
      $job_data = $all_job_data[$jid];
   }
   else {
@@ -308,7 +308,7 @@ function blast_ui_blastx_advanced_options_form_submit($form, $form_state) {
 function blast_ui_blastp_advanced_options_form(&$form, $form_state) {
   $all_job_data = variable_get('job_data', '');
   if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = base64_decode($_GET['jid']);
+     $jid = blast_ui_reveal_secret($_GET['jid']);
      $job_data = $all_job_data[$jid];
   }
   else {
@@ -970,7 +970,7 @@ function ajax_dependent_dropdown_callback($form, $form_state) {
 function blast_ui_tblastn_advanced_options_form(&$form, $form_state) {
   $all_job_data = variable_get('job_data', '');
   if (isset($_GET['jid']) && isset($all_job_data)) {    
-     $jid = base64_decode($_GET['jid']);
+     $jid = blast_ui_reveal_secret($_GET['jid']);
      $job_data = $all_job_data[$jid];
   }
   else {

+ 3 - 3
includes/blast_ui.form_per_program.inc

@@ -28,7 +28,7 @@ function blast_ui_per_blast_program_form($form, $form_state) {
   //   Approach: persist the form data and read it back using JobID
   $job_data = variable_get('job_data', '');
   if (isset($_GET['jid']) && isset($job_data)) {    
-    $jid = base64_decode($_GET['jid']);
+    $jid = blast_ui_reveal_secret($_GET['jid']);
   }  
   else {
     $job_data = array();
@@ -512,7 +512,7 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
        session_start();
     }
     $sid = session_id();
-    $job_encode_id = base64_encode($job_id);
+    $job_encode_id = blast_ui_make_secret($job_id);
     $job_url = "blast/report/$job_encode_id";
 
     $all_jobs = $_SESSION['all_jobs'];
@@ -534,7 +534,7 @@ your sequence headers include pipes (i.e.: | ) they adhere to '
     tripal_jobs_launch(1, $job_id);
     
     //Encode the job_id
-    $job_encode_id = base64_encode($job_id);
+    $job_encode_id = blast_ui_make_secret($job_id);
     
     // Redirect to the BLAST results page
     drupal_goto("blast/report/$job_encode_id");

+ 1 - 1
theme/blast_report.tpl.php

@@ -332,7 +332,7 @@ else {
 <p><?php print l(
   'Edit this query and re-submit', 
   $blast_job->form_options['job_url'],
-  array('query' => array('jid' => base64_encode($job_id))));
+  array('query' => array('jid' => blast_ui_make_secret($job_id))));
 ?></p>
 </div>
 

+ 135 - 1
theme/blast_ui.theme.inc

@@ -87,4 +87,138 @@ function blast_ui_theme_registry_alter(&$theme_registry) {
       }
     }
   }
-}
+}
+
+/**
+ * Makes the tripal job_id unrecognizable.
+ * 
+ * @param $job_id
+ *   The tripal job_id of the blast you want to make secret.
+ *
+ * @return
+ *   A short string representing the job_id.
+ */
+function blast_ui_make_secret($job_id) {
+
+  $mapping = blast_ui_secret_mapping();
+  $secret = str_replace(array_keys($mapping), $mapping, $job_id);
+  
+  return $secret;
+}
+
+/**
+ * Reveals the true job_id for your secret blast result.
+ *
+ * @param $secret
+ *    The job_id previously made secret by blast_ui_make_secret().
+ *
+ * @return
+ *    The revealed tripal job_id.
+ */
+function blast_ui_reveal_secret($secret) {
+
+  $mapping = blast_ui_secret_mapping(TRUE);
+  $job_id = str_replace(array_keys($mapping), $mapping, $secret);
+  
+  // Check that the job_id exists if it is an integer.
+  if (is_integer($job_id)) {
+
+    $exists = db_query('SELECT job_id FROM {tripal_jobs} WHERE job_id=:id', array(':id' => $job_id))->fetchField();
+    if (!$exists) {
+      tripal_report_error(
+        'blast_ui',
+        TRIPAL_ERROR,
+        'Unable to decode the blast job_id from :id.',
+        array(':id' => $secret)
+      );
+    }
+    else {
+      return $job_id;
+    }
+  }  
+  // Last ditch effort: maybe this job was encoded before the upgrade?
+  else {
+  
+    $job_id = base64_decode($secret);
+    $exists = db_query('SELECT job_id FROM {tripal_jobs} WHERE job_id=:id', array(':id' => $job_id))->fetchField();
+    if (!$exists) {
+      tripal_report_error(
+        'blast_ui',
+        TRIPAL_ERROR,
+        'Unable to decode the blast job_id from :id.',
+        array(':id' => $secret)
+      );
+    }
+    else {
+      return $job_id;
+    }
+  }
+  
+  return FALSE;
+}
+
+/**
+ * A single location for keeping track of the mapping used in our secrets.
+ */
+function blast_ui_secret_mapping($reveal = FALSE) {
+  $mapping = array(
+    1 => 'P',
+    2 => 'sA',
+    3 => 'b',
+    4 => 'Q',
+    5 => 'Hi',
+    6 => 'yt',
+    7 => 'f',
+    8 => 'zE',
+    9 => 'Km',
+    0 => 'jVo',
+  );
+  
+  // Since this is an open-source module with all the code publically available, 
+  // our secret is not very secret... We are ok with this since the liklihood of 
+  // profiting by stealing random blast results is pretty low. That said, if this bothers
+  // you, feel free to implement the following function in a private module to change
+  // this mapping to something that cannot easily be looked up on github. ;-).
+  // NOTE: Ensure that the mapping you come up with is unique to ensure that the
+  // job_id can be consistently revealed or your users might end up unable to find 
+  // their own blast results...
+  if (function_exists('private_make_mapping_ultra_secret')) {
+    $mapping = private_make_mapping_ultra_secret($mapping);
+  }
+  
+  if ($reveal) {
+    return array_flip($mapping);
+  }
+  else {
+    return $mapping;
+  }
+}
+
+/**
+ * Tests your secret mapping over a set of random integers 
+ * to ensure the job_id can be recovered.
+ *
+ * @param $num_iterations
+ *    An integer representing the number of times you wish to test your mapping.
+ */
+function blast_ui_test_secret_mapping($num_iterations = 10000) {
+
+  $all_work = TRUE;
+  
+  for($i = 0; $i <= $num_iterations; $i++) {
+    $job_id = mt_rand(0,100000);
+    
+    $secret = blast_ui_make_secret($job_id);
+    $recovered_job_id = blast_ui_reveal_secret($secret);
+    
+    if ($job_id != $recovered_job_id) {
+      drupal_set_message("Unable to recover job_id: $job_id; Secret: $secret.",'error');
+      $all_work = FALSE;
+    }
+  }
+  
+  if ($all_work) {
+    drupal_Set_message("Secret Mapping works over $num_iterations iterations with random integers.");
+  }
+  
+}