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