JAL-1807 update
[jalviewjs.git] / site / php / jsmol.php
1 <?php
2
3 // jsmol.php
4 // Bob Hanson hansonr@stolaf.edu 1/11/2013
5 //
6 // 23 Mar 2015 -- checking for missing :// in queries
7 // 2 Feb 2014 -- stripped of any exec calls and image options-- this was for JSmol image option - abandoned
8 // 30 Oct 2013 -- saveFile should not convert " to _
9 // 30 Sep 2013 -- adjusted error handling to only report E_ERROR not E_WARNING
10 // 7 Sep 2013 -- adding PHP error handling
11 //
12 //////// note to administrators:
13 //
14 // from http://us3.php.net/file_get_contents: 
15 //
16 // A URL can be used as a filename with this function if the fopen wrappers 
17 // have been enabled. See fopen() for more details on how to specify the 
18 // filename. See the Supported Protocols and Wrappers for links to information 
19 // about what abilities the various wrappers have, notes on their usage, and 
20 // information on any predefined variables they may provide.
21 ///////
22 //
23 // Server-side Jmol delivers:
24 //   simple relay for cross-domain files
25 //
26 //   options:
27 //
28 //   call
29 //         "saveFile"
30 //             returns posted data in "data=" with mime type "mimetype=" to file name "filename="
31 //         "getInfoFromDatabase" 
32 //             returns XML data
33 //             requires database="=" (RCSB REST service)
34 //         "getRawDataFromDatabase"
35 //               "_" 
36 //                  just use $query
37 //               (anything else)
38 //                  use $database.$query
39 //
40 //   encoding
41 //         ""        no encoding (default)
42 //         "base64"  BASE64-encoded binary files for Chrome synchronous AJAX
43 //                      prepends ";base64," to encoded output  
44 //
45 // simple server tests:
46 //
47 // http://foo.wherever/jsmol.php?call=getRawDataFromDatabase&database=_&query=http://chemapps.stolaf.edu/jmol/data/t.pdb.gz
48 // http://goo.wherever/jsmol.php?call=getRawDataFromDatabase&database=_&query=http://chemapps.stolaf.edu/jmol/data/t.pdb.gz&encoding=base64
49
50
51 $myerror = "";
52
53 function handleError($severity, $msg, $filename, $linenum) {
54   global $myerror;
55   switch($severity) {
56   case E_ERROR:
57     $myerror = "PHP error:$severity $msg $filename $linenum";
58     break;
59   }
60   return true;
61 }
62
63 set_error_handler("handleError");
64
65 function getValueSimple($json, $key, $default) {
66  if ($json == "") {
67         $val = $_REQUEST[$key];
68  } else {
69  // just do a crude check for "key"..."value"  -- nothing more than that;
70  // only for very simple key/value pairs; mostly because we don't have the JSON
71  // module set up for our server.
72
73         list($junk,$info) = explode('"'.$key.'"', $json, 2);
74         list($junk,$val) = explode('"', $info, 3);
75         if ($val == "") {
76                 $val = str_replace('"','_',$_REQUEST[$key]);
77         }
78  }
79  if ($val == "") {
80    $val = $default;
81  }
82  return $val;
83 }
84
85 if ($_GET['isform']=="true") {
86         $values = "";
87 } else {
88         $values= file_get_contents("php://input");
89 }
90 $encoding = getValueSimple($values, "encoding", "");
91 $call = getValueSimple($values, "call", "getRawDataFromDatabase");
92 $query = getValueSimple($values, "query", "http://cactus.nci.nih.gov/chemical/structure/ethanol/file?format=sdf&get3d=True");
93 $database = getValueSimple($values, "database", "_");
94
95 $imagedata = "";
96 $contentType = "";
97 $output = "";
98 $isBinary = false;
99 $filename = "";
100
101 if ($call == "getInfoFromDatabase") {
102   // TODO: add PDBe annotation business here
103         if ($database == '=') {
104                 $restQueryUrl = "http://www.pdb.org/pdb/rest/search";
105                 $restReportUrl = "http://www.pdb.org/pdb/rest/customReport";
106                 $xml = "<orgPdbQuery><queryType>org.pdb.query.simple.AdvancedKeywordQuery</queryType><description>Text Search</description><keywords>$query</keywords></orgPdbQuery>";
107                 $context = stream_context_create(array('http' => array(
108                         'method' => 'POST',
109                         'header' => 'Content-Type: application/x-www-form-urlencoded',
110                         'content' => $xml))
111                 );
112                 $output = file_get_contents($restQueryUrl, false, $context);
113                 $n = strlen($output)/5;
114                 if ($n == 0) {
115                         $output = "ERROR: \"$query\" not found";
116                 } else {
117                         if (strlen($query) == 4 && $n != 1) {
118                                 $QQQQ = strtoupper($query);
119                                 if (strpos("123456789", substr($QQQQ, 0, 1)) == 0 && strpos($output, $QQQQ) > 0) {
120                                         $output = "$QQQQ\n".$output.str_replace("$QQQQ\n", "",$output);
121                                 }                 
122                         }
123                         if ($n > 50) {
124                                 $output = substr($output, 0, 250);
125                         }
126                         $output = str_replace("\n",",",$output);
127                         //http://www.rcsb.org/pdb/rest/customReport?pdbids=1crn,1d66,1blu,&customReportColumns=structureId,structureTitle
128                         $output = $restReportUrl."?pdbids=".$output."&customReportColumns=structureId,structureTitle";
129                         $output = "<result query=\"$query\" count=\"$n\">".file_get_contents($output)."</result>";
130                 }
131         } else {
132           $myerror = "jsmol.php cannot use $call with $database";
133         }
134         
135 } else if ($call == "getRawDataFromDatabase") {
136         $isBinary = (strpos(".gz", $query) >= 0);
137                 if ($database != "_")
138                         $query = $database.$query;
139                 if (strpos($query, '://') == 0) {
140       $output = "";
141     } else if (strpos($query, '?POST?') > 0) {
142                         list($query,$data) = explode('?POST?', $query, 2);
143                         $context = stream_context_create(array('http' => array(
144                                 'method' => 'POST',
145                                 'header' => 'Content-Type: application/x-www-form-urlencoded',
146                                 'content' => $data))
147                         );
148                         $output = file_get_contents($query, false, $context);
149                 } else {
150                         $output = file_get_contents($query);
151                 }
152 } else if ($call == "saveFile") {
153         $imagedata = $_REQUEST["data"];//getValueSimple($values, "data", ""); don't want to convert " to _ here
154         $filename = getValueSimple($values, "filename", "");
155         $contentType = getValueSimple($values, "mimetype", "application/octet-stream");
156         if ($encoding == "base64") {
157                 $imagedata = base64_decode($imagedata);
158                 $encoding = "";
159         }
160 } else {
161         $myerror = "jsmol.php unrecognized call: $call";
162 }
163
164 ob_start();
165
166  if ($myerror != "") {
167    $output = $myerror;
168  } else { 
169    if ($imagedata != "") {
170         $output = $imagedata;
171         header('Content-Type: '.$contentType);
172         if ($filename != "") {
173           header('Content-Description: File Transfer');
174                 header("Content-Disposition: attachment; filename=\"$filename\"");
175       header('Content-Transfer-Encoding: binary');
176       header('Expires: 0');
177       header('Cache-Control: must-revalidate');
178       header('Pragma: public');
179         }
180    } else {
181         header('Access-Control-Allow-Origin: *');
182         if ($isBinary) {
183                 header('Content-Type: text/plain; charset=x-user-defined');
184         } else {
185                 header('Content-Type: application/json');
186         }
187    }
188    if ($encoding == "base64") {
189          $output = ";base64,".base64_encode($output);
190    }
191  } 
192  header('Last-Modified: '.date('r'));
193  header('Accept-Ranges: bytes');
194  header('Content-Length: '.strlen($output));
195  print($output);
196 ob_end_flush();
197 ?>
198