function createPaymentRequest($params, &$formErrors) { $memcache = new Memcache(); $memcache->connect('localhost', 11211) or die("Could not connect to memcache"); // $params contains: // merchant / address123 / amount123 / time / expires / memo // payment_url / ACK_message $codec = new \DrSlump\Protobuf\Codec\Binary(); $details = new \payments\PaymentDetails(); $details->setTime(time() + (int) $params['time']); if ($params['expires'] != "never") { $details->setExpires(time() + (int) $params['expires']); } setField($params, 'memo', array($details, 'setMemo')); $testnet = false; $totalAmount = 0; $nAddresses = 0; for ($i = 1; $i <= 3; $i++) { $field = "address" . $i; if (!empty($params[$field])) { $output = new \payments\Output(); $r = address_to_script($params[$field]); if ($r === false) { $script = pubkeys_to_script($params[$field]); if ($script === false) { $formErrors[$field] = "Invalid address/pubkey"; continue; } $r = array(true, $script); } $testnet = $r[0]; $output->setScript($r[1]); $output->setAmount($params["amount" . $i] * 100000000.0); $totalAmount += $params["amount" . $i]; $nAddresses += 1; $details->addOutputs($output); // Testnet only, we don't want anybody to be able to create // real-money payment requests // from bitcoincore.org/gavinandresen@gmail.com: if (!$testnet && $params['merchant'] != "None") { $formErrors[$field] = "Testnet-only addresses, please"; return NULL; } } } if ($testnet) { $details->setNetwork("test"); } if (isset($params['payment_url'])) { /* Generate a unique id for this request: */ $id = uniqid(mySecret($memcache)); /* ... store it in merchant data: */ $details->setMerchantData($id); $ackURL = AbsoluteURL('') . "payACK.php"; $details->setPaymentUrl($ackURL); if (isset($params['ACK_message'])) { $memcache->set($id, $params['ACK_message'], 0, 60 * 60 * 24); } else { $memcache->set($id, '', 0, 60 * 60 * 24); } } $paymentRequest = new \payments\PaymentRequest(); $serialized = $details->serialize($codec); $paymentRequest->setSerializedPaymentDetails($serialized); // Signed? if ($params['merchant'] != "None") { $certK = $params['merchant'] . "certificate"; $keyK = $params['merchant'] . "key"; $certChain = new \payments\X509Certificates(); $cachedCertChain = $memcache->get($certK); if ($cachedCertChain === FALSE) { $leafCert = file_get_contents("/home/gavin/.certs/" . $params['merchant'] . ".crt"); $certs = fetch_chain($leafCert); foreach ($certs as $cert) { $certChain->addCertificate($cert); } $cachedCertChain = $certChain->serialize($codec); $memcache->set($certK, $cachedCertChain); } else { $certChain->parse($cachedCertChain); } $paymentRequest->setPkiType("x509+sha1"); $paymentRequest->setPkiData($certChain->serialize($codec)); $priv_key = file_get_contents("/home/gavin/.certs/" . $params['merchant'] . ".key"); $pkeyid = openssl_get_privatekey($priv_key); $paymentRequest->setSignature(""); $dataToSign = $paymentRequest->serialize($codec); $signature = ""; $result = openssl_sign($dataToSign, $signature, $pkeyid, OPENSSL_ALGO_SHA1); if ($signature === FALSE) { return "ERROR: signing failed.\n"; } $paymentRequest->setSignature($signature); } $data = $paymentRequest->serialize($codec); if (isset($params['produce_uri'])) { $urlParams = array(); $hash = hash('ripemd128', $data); $memcache->set($hash, $data, FALSE, 60 * 60 * 24); /* cache for 24 hours */ // f.php is fetch payment request from memcache: $urlParams['r'] = AbsoluteURL('') . "f.php?h=" . $hash; if ($nAddresses == 1 && $totalAmount > 0) { $urlParams['amount'] = $totalAmount; } if ($nAddresses == 1) { $url = AddArgsToURL("bitcoin:" . $params["address1"], $urlParams); } else { $url = AddArgsToURL("bitcoin:", $urlParams); } return MakeAnchor("CLICK TO PAY", $url); } header('Content-Type: application/bitcoin-paymentrequest'); $filename = "r" . (string) time() . ".bitcoinpaymentrequest"; header('Content-Disposition: inline; filename=' . $filename); header('Content-Transfer-Encoding: binary'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . (string) strlen($data)); echo $data; exit(0); }
function ShowRun($runidx) { $runidx = addslashes($runidx); $exptidx = $this->exptidx(); $guid = $this->guid(); $vers = $this->vers(); $template = $this->template(); $query_result = DBQueryFatal("select r.* from experiment_runs as r " . "left join experiment_template_instances as i on " . " i.exptidx=r.exptidx " . "where r.exptidx='{$exptidx}' and r.idx='{$runidx}'"); if (!mysql_num_rows($query_result)) { return; } $row = mysql_fetch_array($query_result); $start = $row['start_time']; $stop = $row['stop_time']; $runid = $row['runid']; $start_tag = $row['starting_archive_tag']; $end_tag = $row['ending_archive_tag']; $description = $row['description']; $hidden = $row['hidden']; # Run descriptions are metatdata that can be changed. # But use a naming convention. $desc_metaname = "__run_description_{$exptidx}_{$runidx}"; $desc_metadata = $template->LookupMetadataByName($desc_metaname); if (!isset($stop)) { $stop = " "; } SUBPAGESTART(); SUBMENUSTART("Run Options"); WRITESUBMENUBUTTON("Export Record", CreateURL("template_export", $this, "runidx", $runidx)); WRITESUBMENUBUTTON("Revise Record", CreateURL("record_revise", $this, "runidx", $runidx)); if ($hidden) { WRITESUBMENUBUTTON("UnHide Record", CreateURL("toggle", $this, "runidx", $runidx, "type", "hiderun", "value", 0)); } else { WRITESUBMENUBUTTON("Hide Record", CreateURL("toggle", $this, "runidx", $runidx, "type", "hiderun", "value", 1)); } if (isset($end_tag) && $end_tag != "") { WRITESUBMENUBUTTON("View Archive", CreateURL("archive_view", $this, "tag", $end_tag)); } SUBMENUEND(); echo "<center>\n"; echo "<table border=0 bgcolor=#000 color=#000 class=stealth " . " cellpadding=0 cellspacing=0>\n"; echo "<tr valign=top>"; echo "<td class=stealth align=center>\n"; echo "<center>\n <h3>Run Details</h3>\n </center>\n"; echo "<table align=center cellpadding=2 cellspacing=2 border=1>\n"; ShowItem("Template", MakeLink("template", "guid={$guid}&version={$vers}", "{$guid}/{$vers}")); ShowItem("Instance", MakeLink("instance", "instance={$exptidx}", "{$exptidx}")); ShowItem("ID", $runidx); if ($hidden) { ShowItem("Hidden", "<font color=red>Yes</font>"); } if ($description && $description != "") { $onmouseover = MakeMouseOver($description); if (strlen($description) > 40) { $description = substr($description, 0, 40) . " <b>... </b>"; } } else { $onmouseover = ""; $description = "Click to Add"; } # If no metadata, assume its for an instance prior to modifiable # instance descriptions. if ($desc_metadata) { $desc_anchor = MakeAnchor(CreateURL("template_metadata", $template, $desc_metadata) . "&action=modify", $description, $onmouseover); } else { $desc_anchor = MakeAnchor(CreateURL("template_metadata", $template) . "&action=add" . "&metadata_type=run_description" . "&formfields[name]={$desc_metaname}", $description, $onmouseover); } ShowItem("Description", $desc_anchor); ShowItem("Started", $start); ShowItem("Stopped", $stop); ShowItem("Start Tag", $start_tag); ShowItem("End Tag", $end_tag); echo "</table>\n"; echo "</td>\n"; $query_result = DBQueryFatal("select * from experiment_run_bindings " . "where exptidx='{$exptidx}' and runidx='{$runidx}'"); if (mysql_num_rows($query_result)) { $id = "{$exptidx}_{$runidx}_bindings"; echo "<td align=center class=stealth>       </td>\n"; echo "<td align=center class=stealth>\n"; AddSortedTable($id); echo "<center>\n <h3>Run Bindings</h3>\n </center> \n <table id='{$id}'\n align=center border=1 cellpadding=5 cellspacing=2>\n"; echo "<thead class='sort'>\n"; echo "<tr>\n <th>Name</th>\n <th>Value</th>\n </tr>\n"; echo "</thead>\n"; while ($row = mysql_fetch_array($query_result)) { $name = $row['name']; $value = $row['value']; if (!isset($value)) { $value = " "; } echo "<tr>\n <td>{$name}</td>\n <td>{$value}</td>\n </tr>\n"; } echo "</table>\n"; echo "</td>\n"; } echo "</tr>\n"; echo "</table>\n"; $this->ShowRunAnnotation($runidx); echo "</center>\n"; SUBPAGEEND(); }