Add Google Analytics
Add Google Analytics

<?php  
 
// Returns portfolio scraped live from directory.gov.au  
// or null if can't find a portfolio  
function agency2portfolio ($agency) {  
static $cache = array();  
if (isset($cache[$agency])) { return $cache[$agency]; }  
$c = curl_init('http://www.directory.gov.au/searchres.php');  
curl_setopt($c, CURLOPT_POST, true);  
curl_setopt($c, CURLOPT_HEADER, false);  
curl_setopt($c, CURLOPT_RETURNTRANSFER, true);  
curl_setopt($c, CURLOPT_REFERER, 'http://www.directory.gov.au/adsearch.php');  
curl_setopt($c, CURLOPT_USERAGENT, 'Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3');  
curl_setopt($c, CURLOPT_POSTFIELDS, array(  
'advkeywordfield' => '',  
'advorgunitfield' => $agency,  
'advrolefield' => '',  
'advsection' => 'All',  
'advsurnamefield' => '',  
'search' => 'Submit Query'  
));  
$results = curl_exec($c);  
 
if (preg_match('#<span\s+class="standardlinks"><a\s+href="([^"]+)">#smi', $results, $m)) {  
$nextURL = $m[1];  
} else {  
$cache[$agency] = false; return false;  
}  
 
curl_setopt($c, CURLOPT_URL, 'http://www.directory.gov.au' . $nextURL);  
curl_setopt($c, CURLOPT_HTTPGET, true);  
curl_setopt($c, CURLOPT_REFERER, 'http://www.directory.gov.au/searchres.php');  
$results = curl_exec($c);  
if (preg_match('#portfolios:\s+([^<]+)#ims', $results, $m)) {  
$cache[$agency] = $m[1]; return $m[1];  
} else {  
$cache[$agency] = false; return false;  
}  
}  
 
?>  
 
<?php <?php
  if (php_sapi_name() != "cli") {
include_once("../lib/common.inc.php");  
  include_once ("../lib/common.inc.php");
  auth();
$query = 'update contractnotice set "parentCN" = null where "parentCN" = \'0\''; $query = 'update contractnotice set "parentCN" = null where "parentCN" = \'0\'';
$result = $conn->prepare($query); $result = $conn->prepare($query);
$result->execute(); $result->execute();
$query = 'update contractnotice set "childCN" = null where "childCN" = \'0\''; $query = 'update contractnotice set "childCN" = null where "childCN" = \'0\'';
$result = $conn->prepare($query); $result = $conn->prepare($query);
$result->execute(); $result->execute();
$query = 'select "CNID","parentCN" from contractnotice where char_length("CNID") > 6 and "CNID" like \'%00_\' and "parentCN" is not null'; $query = 'select "CNID","parentCN" from contractnotice where char_length("CNID") > 6 and "CNID" like \'%00_\' and "parentCN" is not null';
// "CNID" not like '%-A%' // "CNID" not like '%-A%'
//$query = 'select "CNID","parentCN" from contractnotice where char_length("CNID") > 8 and "CNID" like \'%00__\' and "parentCN" is not null'; //$query = 'select "CNID","parentCN" from contractnotice where char_length("CNID") > 8 and "CNID" like \'%00__\' and "parentCN" is not null';
$result = $conn->prepare($query); $result = $conn->prepare($query);
$result->execute(); $result->execute();
foreach ($result->fetchAll() as $record) { foreach ($result->fetchAll() as $record) {
$oldCN = $record['CNID']; $oldCN = $record['CNID'];
$parentCN = substr($oldCN, 0, -3); $parentCN = substr($oldCN, 0, -3);
//$parentCN = substr($oldCN, 0, -4); //$parentCN = substr($oldCN, 0, -4);
if ($parentCN == $record['parentCN']) { if ($parentCN == $record['parentCN']) {
$newCN = $parentCN . "-A" . substr($oldCN, -1); $newCN = $parentCN . "-A" . substr($oldCN, -1);
//$newCN = $parentCN . "-A" . substr($oldCN, -2); //$newCN = $parentCN . "-A" . substr($oldCN, -2);
$updateresult = $conn->exec('UPDATE contractnotice SET "CNID" = \'' . $newCN . '\' where "CNID" = \'' . $oldCN . '\';'); $updateresult = $conn->exec('UPDATE contractnotice SET "CNID" = \'' . $newCN . '\' where "CNID" = \'' . $oldCN . '\';');
   
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
   
if ($errors[1] == 7) { if ($errors[1] == 7) {
echo "$oldCN => $newCN (from parent CN $parentCN) BUT already exists so deleting this record<br>\n"; echo "$oldCN => $newCN (from parent CN $parentCN) BUT already exists so deleting this record<br>\n";
$updateresult = $conn->exec('delete from contractnotice where "CNID" = \'' . $oldCN . '\';'); $updateresult = $conn->exec('delete from contractnotice where "CNID" = \'' . $oldCN . '\';');
   
}else if ($errors[1] == 0) { }else if ($errors[1] == 0) {
echo "$oldCN => $newCN (from parent CN $parentCN) <br>\n"; echo "$oldCN => $newCN (from parent CN $parentCN) <br>\n";
}else }else
print_r($errors); print_r($errors);
} else { } else {
echo "parent CN unexpected - $oldCN doesn't look like child of {$record['parentCN']}, rather the ID suggests child of $parentCN <br>\n"; echo "parent CN unexpected - $oldCN doesn't look like child of {$record['parentCN']}, rather the ID suggests child of $parentCN <br>\n";
} }
} }
  }
   
<?php <?php
  if (php_sapi_name() != "cli") {
   
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
  auth();
$contractNoticeFields = array( $contractNoticeFields = array(
"importFile", "importFile",
"agencyName", "agencyName",
"parentCN", "parentCN",
"CNID", "CNID",
"publishDate", "publishDate",
"amendDate", "amendDate",
"contractStart", "contractStart",
"contractEnd", "contractEnd",
"value", "value",
"description", "description",
"agencyID", "agencyID",
"category", "category",
"procurementMethod", "procurementMethod",
"atmID", "atmID",
"SONID", "SONID",
"confidentialityContract", "confidentialityContract",
"confidentialityContractReason", "confidentialityContractReason",
"confidentialityOutputs", "confidentialityOutputs",
"confidentialityOutputsReason", "confidentialityOutputsReason",
"consultancy", "consultancy",
"consultancyReason", "consultancyReason",
"amendmentReason", "amendmentReason",
"supplierName", "supplierName",
"supplierAddress", "supplierAddress",
"supplierCity", "supplierCity",
"supplierPostcode", "supplierPostcode",
"supplierCountry", "supplierCountry",
"supplierABNExempt", "supplierABNExempt",
"supplierABN", "supplierABN",
"contactBranch", "contactBranch",
"contactDivision", "contactDivision",
"contactPostcode" "contactPostcode"
); );
   
$contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', $contractNoticeFields) . '") VALUES ( '; $contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', $contractNoticeFields) . '") VALUES ( ';
foreach ($contractNoticeFields as $key => $f) { foreach ($contractNoticeFields as $key => $f) {
$contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?"; $contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?";
} }
$contractNoticeInsertQ.= ");"; $contractNoticeInsertQ.= ");";
$contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ); $contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ);
   
function processFile($fpath) { function processFile($fpath) {
global $conn, $contractNoticeFields, $contractNoticeInsertQ; global $conn, $contractNoticeFields, $contractNoticeInsertQ;
$row = 1; $row = 1;
$handle = fopen($fpath, "r"); $handle = fopen($fpath, "r");
//"t" mode string translates windows line breaks to unix //"t" mode string translates windows line breaks to unix
$datamapping0712 = array( $datamapping0712 = array(
"Agency" => "agencyName", "Agency" => "agencyName",
"Parent CN ID" => "parentCN", "Parent CN ID" => "parentCN",
"CN ID" => "CNID", "CN ID" => "CNID",
"Publish Date" => "publishDate", "Publish Date" => "publishDate",
"Amendment Date" => "amendDate", "Amendment Date" => "amendDate",
"Status" => "", "Status" => "",
"StartDate" => "contractStart", "StartDate" => "contractStart",
"EndDate" => "contractEnd", "EndDate" => "contractEnd",
"Value" => "value", "Value" => "value",
"Description" => "description", "Description" => "description",
"Agency Ref Id" => "agencyID", "Agency Ref Id" => "agencyID",
"Agency Ref. ID" => "agencyID", "Agency Ref. ID" => "agencyID",
"Category" => "category", "Category" => "category",
"Procurement Method" => "procurementMethod", "Procurement Method" => "procurementMethod",
"ATM ID" => "atmID", "ATM ID" => "atmID",
"SON ID" => "SONID", "SON ID" => "SONID",
"Confidentiality - Contract" => "confidentialityContract", "Confidentiality - Contract" => "confidentialityContract",
"Confidentiality - Contract Reason(s)" => "confidentialityContractReason", "Confidentiality - Contract Reason(s)" => "confidentialityContractReason",
"Confidentiality - Outputs" => "confidentialityOutputs", "Confidentiality - Outputs" => "confidentialityOutputs",
"Confidentiality - Outputs Reason(s)" => "confidentialityOutputsReason", "Confidentiality - Outputs Reason(s)" => "confidentialityOutputsReason",
"Consultancy" => "consultancy", "Consultancy" => "consultancy",
"Consultancy Reason(s)" => "consultancyReason", "Consultancy Reason(s)" => "consultancyReason",
"Amendment Reason" => "amendmentReason", "Amendment Reason" => "amendmentReason",
"Supplier Name" => "supplierName", "Supplier Name" => "supplierName",
"Supplier Address" => "supplierAddress", "Supplier Address" => "supplierAddress",
"Supplier City" => "supplierCity", "Supplier City" => "supplierCity",
"Supplier Postcode" => "supplierPostcode", "Supplier Postcode" => "supplierPostcode",
"Supplier Country" => "supplierCountry", "Supplier Country" => "supplierCountry",
"Supplier ABNExempt" => "supplierABNExempt", "Supplier ABNExempt" => "supplierABNExempt",
"Supplier ABN" => "supplierABN", "Supplier ABN" => "supplierABN",
"Agency Branch" => "contactBranch", "Agency Branch" => "contactBranch",
"Agency Divison" => "contactDivision", "Agency Divison" => "contactDivision",
"Agency Postcode" => "contactPostcode", "Agency Postcode" => "contactPostcode",
"" => "" "" => ""
); );
$headers; $headers;
   
while (($data = fgetcsv($handle, 1000, "\t")) !== false) { while (($data = fgetcsv($handle, 1000, "\t")) !== false) {
$num = count($data); $num = count($data);
if ($row == 3) { if ($row == 3) {
$headers = $data; $headers = $data;
} elseif ($row > 3) { } elseif ($row > 3) {
if ($num > count($datamapping0712)) { if ($num > count($datamapping0712)) {
die("<font color=red>Error in data import; data mapping fields out of bounds or changed</font><br>" . $fname . print_r($data)); die("<font color=red>Error in data import; data mapping fields out of bounds or changed</font><br>" . $fname . print_r($data));
} }
$contractNoticeInsert = Array(); $contractNoticeInsert = Array();
$supplierInsert = Array(); $supplierInsert = Array();
$agencyInsert = Array(); $agencyInsert = Array();
$contractNoticeInsert[] = $fpath; $contractNoticeInsert[] = $fpath;
$keys = array_keys($datamapping0712); $keys = array_keys($datamapping0712);
for ($c = 0; $c < $num; $c++) { for ($c = 0; $c < $num; $c++) {
$data[$c] = trim($data[$c], "="); $data[$c] = trim($data[$c], "=");
$data[$c] = trim($data[$c], "\""); $data[$c] = trim($data[$c], "\"");
if (in_array(($datamapping0712[$headers[$c]]), $contractNoticeFields)) { if (in_array(($datamapping0712[$headers[$c]]), $contractNoticeFields)) {
if (($datamapping0712[$headers[$c]]) == "parentCN" || ($datamapping0712[$headers[$c]]) == "CNID") { if (($datamapping0712[$headers[$c]]) == "parentCN" || ($datamapping0712[$headers[$c]]) == "CNID") {
$data[$c] = substr($data[$c], 2); // take off the "CN" prefix $data[$c] = substr($data[$c], 2); // take off the "CN" prefix
if ($data[$c] > 0 && $data[$c] != '0') { if ($data[$c] > 0 && $data[$c] != '0') {
$contractNoticeInsert[] = $data[$c]; $contractNoticeInsert[] = $data[$c];
} else { } else {
$contractNoticeInsert[] = null; $contractNoticeInsert[] = null;
} }
} elseif (($datamapping0712[$headers[$c]]) == "supplierABN") { } elseif (($datamapping0712[$headers[$c]]) == "supplierABN") {
if ($data[$c] > 0 && $data[$c] != '0') { if ($data[$c] > 0 && $data[$c] != '0') {
$contractNoticeInsert[] = $data[$c]; $contractNoticeInsert[] = $data[$c];
} else { } else {
$contractNoticeInsert[] = null; $contractNoticeInsert[] = null;
} }
} elseif (($datamapping0712[$headers[$c]]) == "amendDate" || ($datamapping0712[$headers[$c]]) == "publishDate" || ($datamapping0712[$headers[$c]]) == "contractStart" || ($datamapping0712[$headers[$c]]) == "contractEnd") { } elseif (($datamapping0712[$headers[$c]]) == "amendDate" || ($datamapping0712[$headers[$c]]) == "publishDate" || ($datamapping0712[$headers[$c]]) == "contractStart" || ($datamapping0712[$headers[$c]]) == "contractEnd") {
$contractNoticeInsert[] = date('Y-m-d H:i:s', strtotime($data[$c])); $contractNoticeInsert[] = date('Y-m-d H:i:s', strtotime($data[$c]));
} else { } else {
if (strstr("\" =", $data[$c] > 0)) { if (strstr("\" =", $data[$c] > 0)) {
die("Invalid Description field" . $contractNoticeInsert); die("Invalid Description field" . $contractNoticeInsert);
} }
$colvalue = preg_replace('/[^[:print:]]/', '', utf8_encode($data[$c])); $colvalue = preg_replace('/[^[:print:]]/', '', utf8_encode($data[$c]));
   
$contractNoticeInsert[] = $colvalue; $contractNoticeInsert[] = $colvalue;
} }
} }
} }
flush(); flush();
$contractNoticeInsertQ->execute($contractNoticeInsert); $contractNoticeInsertQ->execute($contractNoticeInsert);
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) {
} elseif ($errors[1] == 0) { } elseif ($errors[1] == 0) {
$success++; $success++;
} else { } else {
foreach ($contractNoticeFields as $key => $cnf) { foreach ($contractNoticeFields as $key => $cnf) {
echo var_dump($contractNoticeInsert[$key]) . $cnf . "<br>"; echo var_dump($contractNoticeInsert[$key]) . $cnf . "<br>";
} }
echo $data[2] . " failed CN insert.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n"; echo $data[2] . " failed CN insert.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n";
} }
   
flush(); flush();
//echo "<hr>\n"; //echo "<hr>\n";
} }
$row++; $row++;
} }
fclose($handle); fclose($handle);
$contractNoticeInsertQ->closeCursor(); $contractNoticeInsertQ->closeCursor();
   
return $success; return $success;
} }
   
$path = 'data/'; $path = 'data/';
if ($_REQUEST["fname"] == "") { if ($_REQUEST["fname"] == "") {
echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list<br>"; echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list<br>";
$dhandle = opendir($path); $dhandle = opendir($path);
// define an array to hold the files // define an array to hold the files
$files = array(); $files = array();
if ($dhandle) { if ($dhandle) {
// loop through all of the files // loop through all of the files
while (false !== ($fname = readdir($dhandle))) { while (false !== ($fname = readdir($dhandle))) {
if (($fname != '.') && ($fname != '..')) { if (($fname != '.') && ($fname != '..')) {
$files[date("c", filemtime($path . $fname)) . md5($fname)] = $fname; $files[date("c", filemtime($path . $fname)) . md5($fname)] = $fname;
} }
} }
} }
ksort($files); ksort($files);
foreach ($files as $date => $fname) { foreach ($files as $date => $fname) {
echo "<a href=\"import.php?fname=$fname\">$fname</a>&nbsp;" . filesize($path . $fname) . "&nbsp;" . $date . "<br/>"; echo "<a href=\"import.php?fname=$fname\">$fname</a>&nbsp;" . filesize($path . $fname) . "&nbsp;" . $date . "<br/>";
} }
} else { } else {
$success = 0; $success = 0;
$fname = $_REQUEST["fname"]; $fname = $_REQUEST["fname"];
echo " ============== $fname ============== <br>"; echo " ============== $fname ============== <br>";
flush(); flush();
$success+= processFile($path . $fname, "contractnotice"); $success+= processFile($path . $fname, "contractnotice");
$success+= processFile($path . $fname, "agency"); $success+= processFile($path . $fname, "agency");
$success+= processFile($path . $fname, "supplier"); $success+= processFile($path . $fname, "supplier");
echo "<br> $success records successfully created"; echo "<br> $success records successfully created";
   
flush(); flush();
// run post import data processing // run post import data processing
  //
  $dbConn->exec("update datasets set \"lastUpdated\" = NOW() where title = 'Contract Notices'");
// cn // cn
echo "link amend<br>"; echo "link amend<br>";
include ("linkAmendments.php"); include ("linkAmendments.php");
echo "update UNSPSC<br>"; echo "update UNSPSC<br>";
include ("updateUNSPSC.php"); include ("updateUNSPSC.php");
// agency // agency
//include ("setAgencyStatus.php"); //include ("setAgencyStatus.php");
//include ("setAgencyURLABN.php"); //include ("setAgencyURLABN.php");
} }
  }
?> ?>
   
<?php <?php
include_once("../lib/common.inc.php"); if (php_sapi_name() != "cli") {
   
  include_once ("../lib/common.inc.php");
  auth();
   
// display existing // display existing
   
$unspscresult= $conn->prepare('select * from "UNSPSCcategories";'); $unspscresult= $conn->prepare('select * from "UNSPSCcategories";');
$unspscresult->execute(); $unspscresult->execute();
foreach ($unspscresult->fetchAll() as $row) { foreach ($unspscresult->fetchAll() as $row) {
$unspsc[$row['UNSPSC']] = $row['Title']; $unspsc[$row['UNSPSC']] = $row['Title'];
   
} }
$catsresult = $conn->prepare('SELECT substr( "categoryUNSPSC"::text, 0, 2 ) as cat , SUM( "value" ) as value $catsresult = $conn->prepare('SELECT substr( "categoryUNSPSC"::text, 0, 2 ) as cat , SUM( "value" ) as value
FROM contractnotice FROM contractnotice
GROUP BY cat ;'); GROUP BY cat ;');
echo "<table>"; echo "<table>";
$catsresult->execute(); $catsresult->execute();
foreach ($catsresult->fetchAll() as $row) { foreach ($catsresult->fetchAll() as $row) {
$catName = $unspsc[$row['cat']."0000000"].$row['cat']; $catName = $unspsc[$row['cat']."0000000"].$row['cat'];
if ($row['cat'] == "") $catName = "null"; if ($row['cat'] == "") $catName = "null";
echo "<tr><td>$catName</td><td>".$row['value']."</td></tr>"; echo "<tr><td>$catName</td><td>".$row['value']."</td></tr>";
} }
// import new from file // import new from file
$success = 0; $success = 0;
$fname = "UNSPSC_ECCMA_V13.2_UNDP_V7.csv"; $fname = "UNSPSC_ECCMA_V13.2_UNDP_V7.csv";
echo " ============== $fname ============== <br>"; echo " ============== $fname ============== <br>";
flush(); flush();
$row = 1; $row = 1;
$handle = fopen($path . $fname, "r"); $handle = fopen($path . $fname, "r");
$headers; $headers;
while (($data = fgetcsv($handle, 1000)) !== false) { while (($data = fgetcsv($handle, 1000)) !== false) {
$num = count($data); $num = count($data);
if ($row == 3) { if ($row == 3) {
$headers = $data; $headers = $data;
} elseif ($row > 3) { } elseif ($row > 3) {
//print_r($data); //print_r($data);
$query = 'insert into "UNSPSCcategories" values(".$data[1].","$data[2]");'; $query = 'insert into "UNSPSCcategories" values(".$data[1].","$data[2]");';
//echo $query."<br>\n"; //echo $query."<br>\n";
$conn->exec($query); $conn->exec($query);
flush(); flush();
//echo "<hr>\n"; //echo "<hr>\n";
} }
$row++; $row++;
} }
echo "<br> $success records successfully created"; echo "<br> $success records successfully created";
flush(); flush();
fclose($handle); fclose($handle);
  }
?> ?>
   
<?php <?php
  if (php_sapi_name() != "cli") {
   
include_once ("../lib/common.inc.php"); include_once ("../lib/common.inc.php");
  auth();
$query = 'update contractnotice set "parentCN" = null where "parentCN" = \'0\''; $query = 'update contractnotice set "parentCN" = null where "parentCN" = \'0\'';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
$query = 'update contractnotice set "supplierABN" = null where "supplierABN" = \'0\''; $query = 'update contractnotice set "supplierABN" = null where "supplierABN" = \'0\'';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
$query = 'SELECT c."CNID",c."parentCN",p."childCN" FROM contractnotice as c LEFT OUTER JOIN contractnotice as p on c."parentCN" = p."CNID" $query = 'SELECT c."CNID",c."parentCN",p."childCN" FROM contractnotice as c LEFT OUTER JOIN contractnotice as p on c."parentCN" = p."CNID"
WHERE WHERE
c."parentCN" IS NOT NULL AND p."childCN" IS NULL '; c."parentCN" IS NOT NULL AND p."childCN" IS NULL ';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
if ($row['parentCN'] != 0) { if ($row['parentCN'] != 0) {
$conn->exec('UPDATE contractnotice SET "childCN" = \'' . $conn->exec('UPDATE contractnotice SET "childCN" = \'' .
$row['CNID'] . '\' where "CNID" = \'' . $row['CNID'] . '\' where "CNID" = \'' .
$row['parentCN'] . '\';'); $row['parentCN'] . '\';');
echo 'UPDATE contractnotice SET "childCN" = \'' . echo 'UPDATE contractnotice SET "childCN" = \'' .
$row['CNID'] . '\' where "CNID" = \'' . $row['CNID'] . '\' where "CNID" = \'' .
$row['parentCN'] . '\';'; $row['parentCN'] . '\';';
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
if ($errors[1] == 7 || $errors[1] ==0) if ($errors[1] == 7 || $errors[1] ==0)
echo $row['CNID'] . " linked to parent " . $row['parentCN'] . echo $row['CNID'] . " linked to parent " . $row['parentCN'] .
"<br>\n"; "<br>\n";
else print_r($errors); else print_r($errors);
} }
} }
// also need to eliminate CN 100528/100529 - check for double parent CNs with no childCN, latest sequent CN id keeps childCN = 0 // also need to eliminate CN 100528/100529 - check for double parent CNs with no childCN, latest sequent CN id keeps childCN = 0
$query = 'SELECT "parentCN", array_agg("CNID"), count(*) from contractnotice WHERE "parentCN" IN $query = 'SELECT "parentCN", array_agg("CNID"), count(*) from contractnotice WHERE "parentCN" IN
( (
SELECT "parentCN" SELECT "parentCN"
FROM contractnotice FROM contractnotice
GROUP BY "parentCN" GROUP BY "parentCN"
HAVING COUNT(*) > 1 HAVING COUNT(*) > 1
AND "parentCN" IS NOT NULL AND "parentCN" IS NOT NULL
) )
AND "childCN" IS NULL AND "childCN" IS NULL
GROUP BY "parentCN" having count(*) > 1'; GROUP BY "parentCN" having count(*) > 1';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
$cnids = explode(",",str_replace(Array("{","}"),"",$row['array_agg'])); $cnids = explode(",",str_replace(Array("{","}"),"",$row['array_agg']));
$last_cnid = array_pop($cnids); $last_cnid = array_pop($cnids);
foreach ($cnids as $cnid) { foreach ($cnids as $cnid) {
$conn->exec('UPDATE contractnotice SET "childCN" = \'' . $conn->exec('UPDATE contractnotice SET "childCN" = \'' .
$last_cnid . '\' where "CNID" = \'' . $last_cnid . '\' where "CNID" = \'' .
$cnid . '\';'); $cnid . '\';');
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
if ($errors[1] == 7 || $errors[1] ==0) if ($errors[1] == 7 || $errors[1] ==0)
echo $cnid . " linked to latest child " . $last_cnid . echo $cnid . " linked to latest child " . $last_cnid .
"<br>\n"; "<br>\n";
else print_r($errors); else print_r($errors);
} }
} }
  }
?> ?>
   
<?php <?php
include_once ("../../lib/common.inc.php"); if (php_sapi_name() == "cli") {
  include_once ("../../lib/common.inc.php");
function processFile($fpath, $tablename) function processFile($fpath, $tablename)
{ {
global $conn; global $conn;
echo " ============== $fpath ============== <br>"; echo " ============== $fpath ============== <br>";
flush(); flush();
$row = 1; $row = 1;
$success = 0; $success = 0;
$dupes = 0; $dupes = 0;
$handle = fopen($fpath, "r"); $handle = fopen($fpath, "r");
//"t" mode string translates windows line breaks to unix //"t" mode string translates windows line breaks to unix
$datamapping0507 = array( $datamapping0507 = array(
"Agency" => "agencyName", "Agency" => "agencyName",
"CN ID" => "CNID", "CN ID" => "CNID",
"Publish Date" => "publishDate", "Publish Date" => "publishDate",
"Contract Start Date" => "contractStart", "Contract Start Date" => "contractStart",
"Contract End Date" => "contractEnd", "Contract End Date" => "contractEnd",
"Value (AUD)" => "value", "Value (AUD)" => "value",
"Title" => "description", "Title" => "description",
"Category" => "category", "Category" => "category",
"ATM ID" => "atmID", "ATM ID" => "atmID",
"Supplier Name" => "supplierName", "Supplier Name" => "supplierName",
"LastUpdated" => "amendDate", "LastUpdated" => "amendDate",
"" => "" "" => ""
); );
$headers; $headers;
$contractNoticeFields = array( $contractNoticeFields = array(
"importFile", "importFile",
"CNID", "CNID",
"description", "description",
"agencyName", "agencyName",
"publishDate", "publishDate",
"category", "category",
"contractStart", "contractStart",
"contractEnd", "contractEnd",
"value", "value",
"atmID", "atmID",
"supplierName", "supplierName",
"amendDate" "amendDate"
); );
if ($tablename == "contractnotice") { if ($tablename == "contractnotice") {
$contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', $contractNoticeFields) . '") VALUES ( '; $contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', $contractNoticeFields) . '") VALUES ( ';
foreach ($contractNoticeFields as $key => $f) { foreach ($contractNoticeFields as $key => $f) {
$contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?"; $contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?";
} }
$contractNoticeInsertQ.= ");"; $contractNoticeInsertQ.= ");";
$contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ); $contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ);
} }
while (($data = fgetcsv($handle, 1000, "\t")) !== false) { while (($data = fgetcsv($handle, 1000, "\t")) !== false) {
$num = count($data); $num = count($data);
if ($row == 3) { if ($row == 3) {
$headers = $data; $headers = $data;
} }
elseif ($row > 3) { elseif ($row > 3) {
if ($num > count($datamapping0507)) { if ($num > count($datamapping0507)) {
die("<font color=red>Error in data import; data mapping fields out of bounds or changed</font><br>" . $fname . "data:" .$num. print_r($data ,true). "mapping:" . count($datamapping0507). print_r($datamapping0507 ,true)); die("<font color=red>Error in data import; data mapping fields out of bounds or changed</font><br>" . $fname . "data:" .$num. print_r($data ,true). "mapping:" . count($datamapping0507). print_r($datamapping0507 ,true));
} }
$contractNoticeInsert = Array(); $contractNoticeInsert = Array();
$contractNoticeInsert[] = $fpath; $contractNoticeInsert[] = $fpath;
$keys = array_keys($datamapping0507); $keys = array_keys($datamapping0507);
for ($c = 0; $c < $num; $c++) { for ($c = 0; $c < $num; $c++) {
$data[$c] = trim($data[$c], "="); $data[$c] = trim($data[$c], "=");
$data[$c] = trim($data[$c], "\""); $data[$c] = trim($data[$c], "\"");
if ($tablename == "contractnotice") { if ($tablename == "contractnotice") {
if (in_array(($datamapping0507[$headers[$c]]) , $contractNoticeFields)) { if (in_array(($datamapping0507[$headers[$c]]) , $contractNoticeFields)) {
if (($datamapping0507[$headers[$c]]) == "parentCN" || ($datamapping0507[$headers[$c]]) == "CNID") { if (($datamapping0507[$headers[$c]]) == "parentCN" || ($datamapping0507[$headers[$c]]) == "CNID") {
$data[$c] = substr($data[$c], 2); // take off the "CN" prefix $data[$c] = substr($data[$c], 2); // take off the "CN" prefix
if (!is_numeric($data[$c]) && $data[$c] != "") die($data[$c] . " is not numeric"); if (!is_numeric($data[$c]) && $data[$c] != "") die($data[$c] . " is not numeric");
if ($data[$c] > 0) { if ($data[$c] > 0) {
$contractNoticeInsert[] = $data[$c]; $contractNoticeInsert[] = $data[$c];
} }
else { else {
$contractNoticeInsert[] = 0; $contractNoticeInsert[] = 0;
} }
} }
elseif (($datamapping0507[$headers[$c]]) == "supplierABN") { elseif (($datamapping0507[$headers[$c]]) == "supplierABN") {
if ($data[$c] > 0) { if ($data[$c] > 0) {
$contractNoticeInsert[] = $data[$c]; $contractNoticeInsert[] = $data[$c];
} }
else { else {
$contractNoticeInsert[] = null; $contractNoticeInsert[] = null;
} }
} }
elseif (($datamapping0507[$headers[$c]]) == "amendDate" || ($datamapping0507[$headers[$c]]) == "publishDate" || ($datamapping0507[$headers[$c]]) == "contractStart" || ($datamapping0507[$headers[$c]]) == "contractEnd") { elseif (($datamapping0507[$headers[$c]]) == "amendDate" || ($datamapping0507[$headers[$c]]) == "publishDate" || ($datamapping0507[$headers[$c]]) == "contractStart" || ($datamapping0507[$headers[$c]]) == "contractEnd") {
$contractNoticeInsert[] = date('Y-m-d H:i:s', strtotime($data[$c])); $contractNoticeInsert[] = date('Y-m-d H:i:s', strtotime($data[$c]));
} }
else { else {
if (strstr("\" =", $data[$c] > 0)) { if (strstr("\" =", $data[$c] > 0)) {
die("Invalid Description field" . $contractNoticeInsert); die("Invalid Description field" . $contractNoticeInsert);
} }
$colvalue = preg_replace( '/[^[:print:]]/', '',utf8_encode( $data[$c])); $colvalue = preg_replace( '/[^[:print:]]/', '',utf8_encode( $data[$c]));
   
$contractNoticeInsert[] = $colvalue; $contractNoticeInsert[] = $colvalue;
} }
} }
} }
} }
flush(); flush();
if ($tablename == "contractnotice") { if ($tablename == "contractnotice") {
$contractNoticeInsertQ->execute($contractNoticeInsert); $contractNoticeInsertQ->execute($contractNoticeInsert);
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) {
$dupes++; $dupes++;
} }
elseif ($errors[1] == 0) { elseif ($errors[1] == 0) {
$success++; $success++;
} }
else { else {
foreach ($contractNoticeFields as $key => $cnf) { foreach ($contractNoticeFields as $key => $cnf) {
echo var_dump($contractNoticeInsert[$key]) . $cnf . "<br>"; echo var_dump($contractNoticeInsert[$key]) . $cnf . "<br>";
} }
echo $data[2] . " failed CN insert.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n"; echo $data[2] . " failed CN insert.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n";
} }
} }
flush(); flush();
//echo "<hr>\n"; //echo "<hr>\n";
} }
$row++; $row++;
} }
fclose($handle); fclose($handle);
echo " $dupes duplicate records<br>"; echo " $dupes duplicate records<br>";
echo " $success records successfully created<br>"; echo " $success records successfully created<br>";
flush(); flush();
return $success; return $success;
} }
$path = './'; $path = './';
if ($_REQUEST["fname"] == "") { if ($_REQUEST["fname"] == "") {
echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list<br>"; echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list<br>";
$dhandle = opendir($path); $dhandle = opendir($path);
// define an array to hold the files // define an array to hold the files
$files = array(); $files = array();
if ($dhandle) { if ($dhandle) {
// loop through all of the files // loop through all of the files
while (false !== ($fname = readdir($dhandle))) { while (false !== ($fname = readdir($dhandle))) {
if (($fname != '.') && ($fname != '..') && (!isset($_REQUEST["filter"]) || strpos($fname,$_REQUEST["filter"]) != false)) { if (($fname != '.') && ($fname != '..') && (!isset($_REQUEST["filter"]) || strpos($fname,$_REQUEST["filter"]) != false)) {
echo "<a href=\"import.php?fname=$fname\">$fname</a>&nbsp;" . filesize($path . $fname) . "&nbsp;" . date("c", filemtime($path . $fname)) . "<br/>"; echo "<a href=\"import.php?fname=$fname\">$fname</a>&nbsp;" . filesize($path . $fname) . "&nbsp;" . date("c", filemtime($path . $fname)) . "<br/>";
processFile($path . $fname, "contractnotice"); processFile($path . $fname, "contractnotice");
} }
} }
} }
} }
else { else {
$success = 0; $success = 0;
$fname = $_REQUEST["fname"]; $fname = $_REQUEST["fname"];
$success+= processFile($path . $fname, "contractnotice"); $success+= processFile($path . $fname, "contractnotice");
   
} }
  }
?> ?>
   
<?php <?php
include_once ("../../lib/common.inc.php"); if (php_sapi_name() == "cli") {
  include_once ("../../lib/common.inc.php");
/* /*
update contractnotice set "supplierABN" = a."supplierABN" update contractnotice set "supplierABN" = a."supplierABN"
from contractnotice as cn inner join (select "supplierABN", from contractnotice as cn inner join (select "supplierABN",
"supplierName" from contractnotice where "supplierABN" "supplierName" from contractnotice where "supplierABN"
IS NOT NULL and "supplierABN" != 0) as a on IS NOT NULL and "supplierABN" != 0) as a on
cn."supplierName" = a."supplierName" where cn."supplierName" = a."supplierName" where
cn."CNID"=contractnotice."CNID" and (contractnotice."supplierABN" cn."CNID"=contractnotice."CNID" and (contractnotice."supplierABN"
IS NULL or contractnotice."supplierABN" = 0) */ IS NULL or contractnotice."supplierABN" = 0) */
// http://www.lastcraft.com/browser_documentation.php // http://www.lastcraft.com/browser_documentation.php
// http://code.google.com/p/phpquery/ // http://code.google.com/p/phpquery/
require('phpQuery-onefile.php'); require('phpQuery-onefile.php');
function getURL($url) { function getURL($url) {
//return file_get_contents($url); //return file_get_contents($url);
$ch = curl_init($url); $ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_TIMEOUT, 45); curl_setopt($ch, CURLOPT_TIMEOUT, 45);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
$page = curl_exec($ch); $page = curl_exec($ch);
if (curl_errno($ch)) { if (curl_errno($ch)) {
echo "<font color=red> Database temporarily unavailable: "; echo "<font color=red> Database temporarily unavailable: ";
echo curl_errno($ch) . " " . curl_error($ch); echo curl_errno($ch) . " " . curl_error($ch);
echo $url; echo $url;
echo "</font><br>"; echo "</font><br>";
} }
curl_close($ch); curl_close($ch);
return $page; return $page;
} }
   
   
function getTextFromTHNode($Node, $Text = "") { function getTextFromTHNode($Node, $Text = "") {
if ($Node->tagName == null) if ($Node->tagName == null)
return $Text.$Node->textContent; return $Text.$Node->textContent;
if ($Node->tagName != "td") { if ($Node->tagName != "td") {
$Node = $Node->firstChild; $Node = $Node->firstChild;
if ($Node != null) if ($Node != null)
$Text = getTextFromTHNode($Node, $Text); $Text = getTextFromTHNode($Node, $Text);
   
while($Node->nextSibling != null) { while($Node->nextSibling != null) {
$Text = getTextFromTHNode($Node->nextSibling, $Text); $Text = getTextFromTHNode($Node->nextSibling, $Text);
$Node = $Node->nextSibling; $Node = $Node->nextSibling;
} }
} }
return $Text; return $Text;
} }
   
function getTextFromNode($Node, $Text = "") { function getTextFromNode($Node, $Text = "") {
if ($Node->tagName == null) if ($Node->tagName == null)
return $Text.$Node->textContent; return $Text.$Node->textContent;
if ($Node->tagName != "th" && $Node->tagName != "span") { if ($Node->tagName != "th" && $Node->tagName != "span") {
$Node = $Node->firstChild; $Node = $Node->firstChild;
if ($Node != null) if ($Node != null)
$Text = getTextFromNode($Node, $Text); $Text = getTextFromNode($Node, $Text);
   
while($Node->nextSibling != null) { while($Node->nextSibling != null) {
$Text = getTextFromNode($Node->nextSibling, $Text); $Text = getTextFromNode($Node->nextSibling, $Text);
$Node = $Node->nextSibling; $Node = $Node->nextSibling;
} }
} }
return $Text; return $Text;
} }
function dom_to_array($root) function dom_to_array($root)
{ {
$result = array(); $result = array();
   
if ($root->hasAttributes()) if ($root->hasAttributes())
{ {
$attrs = $root->attributes; $attrs = $root->attributes;
   
foreach ($attrs as $i => $attr) foreach ($attrs as $i => $attr)
$result[$attr->name] = $attr->value; $result[$attr->name] = $attr->value;
} }
   
$children = $root->childNodes; $children = $root->childNodes;
if ($root->childNodes) { if ($root->childNodes) {
if ($children->length == 1) if ($children->length == 1)
{ {
$child = $children->item(0); $child = $children->item(0);
   
if ($child->nodeType == XML_TEXT_NODE) if ($child->nodeType == XML_TEXT_NODE)
{ {
$result['_value'] = $child->nodeValue; $result['_value'] = $child->nodeValue;
   
if (count($result) == 1) if (count($result) == 1)
return $result['_value']; return $result['_value'];
else else
return $result; return $result;
} }
} }
   
$group = array(); $group = array();
   
for($i = 0; $i < $children->length; $i++) for($i = 0; $i < $children->length; $i++)
{ {
$child = $children->item($i); $child = $children->item($i);
   
if (!isset($result[$child->nodeName])) if (!isset($result[$child->nodeName]))
$result[$child->nodeName] = dom_to_array($child); $result[$child->nodeName] = dom_to_array($child);
else else
{ {
if (!isset($group[$child->nodeName])) if (!isset($group[$child->nodeName]))
{ {
$tmp = $result[$child->nodeName]; $tmp = $result[$child->nodeName];
$result[$child->nodeName] = array($tmp); $result[$child->nodeName] = array($tmp);
$group[$child->nodeName] = 1; $group[$child->nodeName] = 1;
} }
   
$result[$child->nodeName][] = dom_to_array($child); $result[$child->nodeName][] = dom_to_array($child);
} }
} }
} }
   
return $result; return $result;
} }
   
function importCN($cnid) { function importCN($cnid) {
global $conn; global $conn;
// check if already complete // check if already complete
$query = 'Select "parentCN" from contractnotice $query = 'Select "parentCN" from contractnotice
where "CNID" = :CNID'; where "CNID" = :CNID';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":CNID", $CN); $query->bindParam(":CNID", $CN);
$query->execute(); $query->execute();
$r = $query->fetch(PDO::FETCH_ASSOC); $r = $query->fetch(PDO::FETCH_ASSOC);
if ($r['parentCN'] == NULL) { if ($r['parentCN'] == NULL) {
$site = "https://www.tenders.gov.au/"; $site = "https://www.tenders.gov.au/";
$searchResult = phpQuery::newDocument(getURL("https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN".$cnid)); $searchResult = phpQuery::newDocument(getURL("https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN".$cnid));
//echo "https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN".$cnid; //echo "https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN".$cnid;
$url = ""; $url = "";
foreach(pq('a') as $a) { foreach(pq('a') as $a) {
if (strpos($a->getAttribute("href"),"public.cn.view") >0 ) { if (strpos($a->getAttribute("href"),"public.cn.view") >0 ) {
//echo $a->getAttribute("href"); //echo $a->getAttribute("href");
$url = $a->getAttribute("href"); $url = $a->getAttribute("href");
break; break;
} }
} }
$cn = phpQuery::newDocument(getURL($site.$url)); $cn = phpQuery::newDocument(getURL($site.$url));
$datamapping0711 = array( $datamapping0711 = array(
"Agency" => "agencyName", "Agency" => "agencyName",
"Parent CN" => "parentCN", "Parent CN" => "parentCN",
"CN ID" => "CNID", "CN ID" => "CNID",
"Publish Date" => "publishDate", "Publish Date" => "publishDate",
"Amendment Date" => "amendDate", "Amendment Date" => "amendDate",
"Status" => "", "Status" => "",
"StartDate" => "contractStart", "StartDate" => "contractStart",
"EndDate" => "contractEnd", "EndDate" => "contractEnd",
"Contract Value (AUD)" => "value", "Contract Value (AUD)" => "value",
"Description" => "description", "Description" => "description",
"Agency Reference ID" => "agencyID", "Agency Reference ID" => "agencyID",
"Category" => "category", "Category" => "category",
"Procurement Method" => "procurementMethod", "Procurement Method" => "procurementMethod",
"ATM ID" => "atmID", "ATM ID" => "atmID",
"SON ID" => "SONID", "SON ID" => "SONID",
"Confidentiality - Contract" => "confidentialityContract", "Confidentiality - Contract" => "confidentialityContract",
"Confidentiality Reason(s) - Contract" => "confidentialityContractReason", "Confidentiality Reason(s) - Contract" => "confidentialityContractReason",
"Confidentiality - Outputs" => "confidentialityOutputs", "Confidentiality - Outputs" => "confidentialityOutputs",
"Confidentiality Reason(s) - Outputs" => "confidentialityOutputsReason", "Confidentiality Reason(s) - Outputs" => "confidentialityOutputsReason",
"Consultancy" => "consultancy", "Consultancy" => "consultancy",
"Consultancy Reason(s)" => "consultancyReason", "Consultancy Reason(s)" => "consultancyReason",
"Amendment Reason" => "amendmentReason", "Amendment Reason" => "amendmentReason",
"Name" => "supplierName", "Name" => "supplierName",
"Postal Address" => "supplierAddress", "Postal Address" => "supplierAddress",
"Town/City" => "supplierCity", "Town/City" => "supplierCity",
"Postcode" => "supplierPostcode", "Postcode" => "supplierPostcode",
"Country" => "supplierCountry", "Country" => "supplierCountry",
"ABN Exempt" => "supplierABNExempt", "ABN Exempt" => "supplierABNExempt",
"ABN" => "supplierABN", "ABN" => "supplierABN",
"Branch" => "contactBranch", "Branch" => "contactBranch",
"Division" => "contactDivision", "Division" => "contactDivision",
"Office Postcode" => "contactPostcode" "Office Postcode" => "contactPostcode"
); );
$cnFields = Array(); $cnFields = Array();
foreach(pq('tr') as $tr) { foreach(pq('tr') as $tr) {
$tra = dom_to_array($tr); $tra = dom_to_array($tr);
if (is_array($tra['th'])) { if (is_array($tra['th'])) {
$fieldName = trim(getTextFromTHNode($tr)); $fieldName = trim(getTextFromTHNode($tr));
} else { } else {
$fieldName = trim(str_replace("/th>","",$tra['th'])); $fieldName = trim(str_replace("/th>","",$tra['th']));
} }
$fieldValue = trim(print_r($tra['td'],true)); $fieldValue = trim(print_r($tra['td'],true));
if ($fieldName == "State/Territory" || $fieldName == "Contact Name" if ($fieldName == "State/Territory" || $fieldName == "Contact Name"
|| $fieldName == "Contact Phone" || $fieldName == "Contact Email" || $fieldName == "Contact Phone" || $fieldName == "Contact Email"
||$fieldName == "Amendments") { ||$fieldName == "Amendments") {
// do nothing // do nothing
} else if ($fieldName == "Contract Period") { } else if ($fieldName == "Contract Period") {
$contractPeriod = explode("to",$fieldValue); $contractPeriod = explode("to",$fieldValue);
$cnFields["contractStart"] = trim($contractPeriod[0]); $cnFields["contractStart"] = trim($contractPeriod[0]);
$cnFields["contractEnd"] = trim($contractPeriod[1]); $cnFields["contractEnd"] = trim($contractPeriod[1]);
} else { } else {
$fieldName = $datamapping0711[$fieldName]; $fieldName = $datamapping0711[$fieldName];
   
if ($fieldName == "parentCN" || $fieldName == "CNID") { if ($fieldName == "parentCN" || $fieldName == "CNID") {
if (is_array($tra['td'])) { if (is_array($tra['td'])) {
$fieldValue = trim(getTextFromNode($tr)); $fieldValue = trim(getTextFromNode($tr));
} }
$fieldValue = substr($fieldValue, 2); // take off the "CN" prefix $fieldValue = substr($fieldValue, 2); // take off the "CN" prefix
} elseif ($fieldName == "description") { } elseif ($fieldName == "description") {
if (is_array($tra['td'])) $fieldValue = print_r($tra['td']['p'],true); if (is_array($tra['td'])) $fieldValue = print_r($tra['td']['p'],true);
} elseif ($fieldName == "value" || $fieldName == "supplierABN") { } elseif ($fieldName == "value" || $fieldName == "supplierABN") {
if (is_array($tra['td'])) { if (is_array($tra['td'])) {
$fieldValue = trim(getTextFromNode($tr)); $fieldValue = trim(getTextFromNode($tr));
} }
$fieldValue = str_replace(Array("$",","," "), "", $fieldValue); $fieldValue = str_replace(Array("$",","," "), "", $fieldValue);
//if (!is_numeric($fieldValue)) $fieldValue = 0; //if (!is_numeric($fieldValue)) $fieldValue = 0;
if ($fieldValue == "Exempt") $fieldValue = NULL; if ($fieldValue == "Exempt") $fieldValue = NULL;
} elseif ($fieldName == "amendDate" || $fieldName == "publishDate" || $fieldName == "contractStart" || $fieldName == "contractEnd") { } elseif ($fieldName == "amendDate" || $fieldName == "publishDate" || $fieldName == "contractStart" || $fieldName == "contractEnd") {
$fieldValue = date('Y-m-d H:i:s', strtotime($fieldValue)); $fieldValue = date('Y-m-d H:i:s', strtotime($fieldValue));
} elseif (is_array($tra['td'])) { } elseif (is_array($tra['td'])) {
$fieldValue = trim(getTextFromNode($tr)); $fieldValue = trim(getTextFromNode($tr));
} }
echo $fieldName. " = " .$fieldValue."<br>\n"; echo $fieldName. " = " .$fieldValue."<br>\n";
$cnFields[$fieldName] = $fieldValue; $cnFields[$fieldName] = $fieldValue;
} }
} }
if (isset($cnFields[""])) { if (isset($cnFields[""])) {
$cnFields["description"] .= $cnFields[""]; $cnFields["description"] .= $cnFields[""];
unset($cnFields[""]); unset($cnFields[""]);
} }
$cnFields["importFile"] = $url; $cnFields["importFile"] = $url;
$contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', array_keys($cnFields)) . '") VALUES ( '; $contractNoticeInsertQ = 'INSERT INTO contractnotice ("' . implode('" , "', array_keys($cnFields)) . '") VALUES ( ';
for($key = 0; $key < sizeof($cnFields); $key++) { for($key = 0; $key < sizeof($cnFields); $key++) {
$contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?"; $contractNoticeInsertQ.= ($key == 0 ? "" : ", ") . "?";
} }
$contractNoticeInsertQ.= ");"; $contractNoticeInsertQ.= ");";
//echo $contractNoticeInsertQ; //echo $contractNoticeInsertQ;
$contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ); $contractNoticeInsertQ = $conn->prepare($contractNoticeInsertQ);
$contractNoticeInsertQ->execute(array_values($cnFields)); $contractNoticeInsertQ->execute(array_values($cnFields));
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) {
echo "Dupe {$cnFields['CNID']}<br>"; echo "Dupe {$cnFields['CNID']}<br>";
} }
elseif ($errors[1] == 0) { elseif ($errors[1] == 0) {
echo "Success insert {$cnFields['CNID']} <br>"; echo "Success insert {$cnFields['CNID']} <br>";
} }
else { else {
foreach ($cnFields as $key => $cnf) { foreach ($cnFields as $key => $cnf) {
echo var_dump($key) . $cnf . "<br>"; echo var_dump($key) . $cnf . "<br>";
} }
echo $cnFields['CNID'] . " failed CN insert.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n"; echo $cnFields['CNID'] . " failed CN insert.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n";
} }
$contractNoticeUpdateQ = 'UPDATE contractnotice SET '; $contractNoticeUpdateQ = 'UPDATE contractnotice SET ';
$count = 0; $count = 0;
foreach ($cnFields as $key => $f) { foreach ($cnFields as $key => $f) {
$count++; $count++;
$contractNoticeUpdateQ.= '"'.$key.'"=? '.($count >= sizeof($cnFields) ? "" : ", "); $contractNoticeUpdateQ.= '"'.$key.'"=? '.($count >= sizeof($cnFields) ? "" : ", ");
} }
$contractNoticeUpdateQ.= ' WHERE "CNID"=?;'; $contractNoticeUpdateQ.= ' WHERE "CNID"=?;';
$cnFields[] = $cnFields["CNID"]; $cnFields[] = $cnFields["CNID"];
//echo $contractNoticeUpdateQ; //echo $contractNoticeUpdateQ;
$contractNoticeUpdateQ = $conn->prepare($contractNoticeUpdateQ); $contractNoticeUpdateQ = $conn->prepare($contractNoticeUpdateQ);
$contractNoticeUpdateQ->execute(array_values($cnFields)); $contractNoticeUpdateQ->execute(array_values($cnFields));
$errors = $conn->errorInfo(); $errors = $conn->errorInfo();
if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) { if ($errors[1] == 7 && strpos($errors[2], "duplicate key")) {
print_r($errors); print_r($errors);
echo "Dupe update {$cnFields['CNID']}<br>"; echo "Dupe update {$cnFields['CNID']}<br>";
} }
elseif ($errors[1] == 0) { elseif ($errors[1] == 0) {
echo "Success update {$cnFields['CNID']} <br>"; echo "Success update {$cnFields['CNID']} <br>";
} }
else { else {
foreach ($cnFields as $key => $cnf) { foreach ($cnFields as $key => $cnf) {
echo var_dump($key) . $cnf . "<br>"; echo var_dump($key) . $cnf . "<br>";
} }
echo $cnFields['CNID'] . " failed CN update.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n"; echo $cnFields['CNID'] . " failed CN update.<br>" . print_r($errors, true) . "<br> row $row <br><br>\n";
} }
} }
} }
function processFile($fpath, $tablename) function processFile($fpath, $tablename)
{ {
global $conn; global $conn;
echo " ============== $fpath ============== <br>"; echo " ============== $fpath ============== <br>";
$handle = fopen($fpath, "r"); $handle = fopen($fpath, "r");
flush(); flush();
$row = 1; $row = 1;
while (($data = fgetcsv($handle, 1000, "\t")) !== false) { while (($data = fgetcsv($handle, 1000, "\t")) !== false) {
if ($row > 3) { if ($row > 3) {
$data[0] = trim($data[0], "="); $data[0] = trim($data[0], "=");
$data[0] = trim($data[0], "\""); $data[0] = trim($data[0], "\"");
if (strpos($data[0], "-A") > 0) { if (strpos($data[0], "-A") > 0) {
echo "Loading {$data[0]} ... <br>\n"; echo "Loading {$data[0]} ... <br>\n";
importCN(str_replace("CN","",$data[0])); importCN(str_replace("CN","",$data[0]));
} }
} }
flush(); flush();
//echo "<hr>\n"; //echo "<hr>\n";
$row++; $row++;
} }
fclose($handle); fclose($handle);
} }
$path = './'; $path = './';
if ($_REQUEST["fname"] == "") { if ($_REQUEST["fname"] == "") {
echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list<br>"; echo "Get files from: https://www.tenders.gov.au/?event=public.reports.list<br>";
$dhandle = opendir($path); $dhandle = opendir($path);
// define an array to hold the files // define an array to hold the files
$files = array(); $files = array();
if ($dhandle) { if ($dhandle) {
// loop through all of the files // loop through all of the files
while (false !== ($fname = readdir($dhandle))) { while (false !== ($fname = readdir($dhandle))) {
if (($fname != '.') && ($fname != '..') && (strpos($fname,".xls")>0)) { if (($fname != '.') && ($fname != '..') && (strpos($fname,".xls")>0)) {
echo "<a href=\"import.php?fname=$fname\">$fname</a>&nbsp;" . filesize($path . $fname) . "&nbsp;" . date("c", filemtime($path . $fname)) . "<br/>"; echo "<a href=\"import.php?fname=$fname\">$fname</a>&nbsp;" . filesize($path . $fname) . "&nbsp;" . date("c", filemtime($path . $fname)) . "<br/>";
processFile($path . $fname, "contractnotice"); processFile($path . $fname, "contractnotice");
} }
} }
} }
} }
else { else {
$success = 0; $success = 0;
$fname = $_REQUEST["fname"]; $fname = $_REQUEST["fname"];
$success+= processFile($path . $fname, "contractnotice"); $success+= processFile($path . $fname, "contractnotice");
   
} }
  }
?> ?>
   
<?php <?php
  if (php_sapi_name() == "cli") {
date_default_timezone_set('Australia/Melbourne'); date_default_timezone_set('Australia/Melbourne');
$split = false; $split = false;
function format_bytes($size) { function format_bytes($size) {
$units = array(' B', ' KB', ' MB', ' GB', ' TB'); $units = array(' B', ' KB', ' MB', ' GB', ' TB');
for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024; for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
return round($size, 2).$units[$i]; return round($size, 2).$units[$i];
} }
   
$days = 4; $days = 4;
if (isset($_REQUEST['days'])) $days = $_REQUEST['days']; if (isset($_REQUEST['days'])) $days = $_REQUEST['days'];
$startDate = strtotime("05-Jun-2008"); $startDate = strtotime("05-Jun-2008");
if (isset($_REQUEST['startDate'])) $startDate = $_REQUEST['startDate']; if (isset($_REQUEST['startDate'])) $startDate = $_REQUEST['startDate'];
   
function getFile($startDate, $days, $minVal, $maxVal) { function getFile($startDate, $days, $minVal, $maxVal) {
global $split; global $split;
$endDate = strtotime(date("Y-m-d", $startDate)." +".$days." days"); $endDate = strtotime(date("Y-m-d", $startDate)." +".$days." days");
$file = date("dMY",$startDate).'to'.date("dMY",$endDate).'val'.$minVal.'to'.$maxVal.'.xls'; $file = date("dMY",$startDate).'to'.date("dMY",$endDate).'val'.$minVal.'to'.$maxVal.'.xls';
echo "Fetching $file ($days days) ($minVal < value < $maxVal )... "; echo "Fetching $file ($days days) ($minVal < value < $maxVal )... ";
$url = "https://www.tenders.gov.au/?event=public.advancedsearch.CNSONRedirect&type=cnEvent&atmType=archived%2Cclosed%2Cpublished%2Cproposed&agencyUUID=&agencyStatus=-1&portfolioUUID=&keyword=&KeywordTypeSearch=AllWord&CNID=&dateType=Publish+Date&dateStart=".date("d-M-Y",$startDate)."&dateEnd=".date("d-M-Y",$endDate)."&supplierName=&supplierABN=&valueFrom=".$minVal."&valueTo=".$maxVal."&ATMID=&AgencyRefId=&consultancy=&download=Download+results"; $url = "https://www.tenders.gov.au/?event=public.advancedsearch.CNSONRedirect&type=cnEvent&atmType=archived%2Cclosed%2Cpublished%2Cproposed&agencyUUID=&agencyStatus=-1&portfolioUUID=&keyword=&KeywordTypeSearch=AllWord&CNID=&dateType=Publish+Date&dateStart=".date("d-M-Y",$startDate)."&dateEnd=".date("d-M-Y",$endDate)."&supplierName=&supplierABN=&valueFrom=".$minVal."&valueTo=".$maxVal."&ATMID=&AgencyRefId=&consultancy=&download=Download+results";
echo "<!-- $url -->"; echo "<!-- $url -->";
$current = file_get_contents($url); $current = file_get_contents($url);
if (strpos($current,"There are no results that match your selection.")> 0 ) { if (strpos($current,"There are no results that match your selection.")> 0 ) {
echo "<font color=red>Empty file!</font><br>"; echo "<font color=red>Empty file!</font><br>";
} }
if (strpos($current,"Your search returned more than 1000 results.") === false) { if (strpos($current,"Your search returned more than 1000 results.") === false) {
file_put_contents($file, $current); file_put_contents($file, $current);
echo "$file saved<br>"; echo "$file saved<br>";
echo format_bytes(filesize($file))."<br>"; echo format_bytes(filesize($file))."<br>";
echo '<a href="?startDate='.$endDate.'&days='.$days.'">Load next '.($days).' days </a><br>'; echo '<a href="?startDate='.$endDate.'&days='.$days.'">Load next '.($days).' days </a><br>';
echo '<a href="?startDate='.$endDate.'&days='.($days*2).'">Load next '.($days*2).' days </a><br>'; echo '<a href="?startDate='.$endDate.'&days='.($days*2).'">Load next '.($days*2).' days </a><br>';
echo '<a href="?startDate='.$endDate.'&days='.$days.'&split=yes">Load next '.($days).' days with split</a><br>'; echo '<a href="?startDate='.$endDate.'&days='.$days.'&split=yes">Load next '.($days).' days with split</a><br>';
flush(); flush();
if (!isset($_REQUEST['split']) && !$split) { if (!isset($_REQUEST['split']) && !$split) {
echo "Success so fetching next $days... <br>"; echo "Success so fetching next $days... <br>";
getFile($endDate, $days, "" , ""); getFile($endDate, $days, "" , "");
} }
return true; return true;
} else { } else {
echo "<font color=red>Too many records!</font><br>"; echo "<font color=red>Too many records!</font><br>";
echo '<a href="?startDate='.$startDate.'&days='.floor($days/2).'">Load '.($days/2).' days instead?</a><br>'; echo '<a href="?startDate='.$startDate.'&days='.floor($days/2).'">Load '.($days/2).' days instead?</a><br>';
echo '<a href="?startDate='.$startDate.'&days='.$days.'&split=yes">Split instead?</a><br>'; echo '<a href="?startDate='.$startDate.'&days='.$days.'&split=yes">Split instead?</a><br>';
flush(); flush();
if (!isset($_REQUEST['split']) && !$split) { if (!isset($_REQUEST['split']) && !$split) {
echo "Failure so splitting ... <br>"; echo "Failure so splitting ... <br>";
doSplit($startDate, $days); doSplit($startDate, $days);
} }
return false; return false;
} }
} }
function doSplit($startDate, $days) { function doSplit($startDate, $days) {
global $split; global $split;
$split = true; $split = true;
set_time_limit(20); set_time_limit(20);
getFile($startDate, $days, 0, 12000); getFile($startDate, $days, 0, 12000);
getFile($startDate, $days, 12000, 16000); getFile($startDate, $days, 12000, 16000);
getFile($startDate, $days, 16000, 20000); getFile($startDate, $days, 16000, 20000);
getFile($startDate, $days, 20000, 30000); getFile($startDate, $days, 20000, 30000);
getFile($startDate, $days, 30000, 40000); getFile($startDate, $days, 30000, 40000);
// getFile($startDate, $days, 40000, 80000); // getFile($startDate, $days, 40000, 80000);
getFile($startDate, $days, 40000, 60000); getFile($startDate, $days, 40000, 60000);
getFile($startDate, $days, 60000, 80000); getFile($startDate, $days, 60000, 80000);
// getFile($startDate, $days, 80000, 300000); // getFile($startDate, $days, 80000, 300000);
getFile($startDate, $days, 80000, 150000); getFile($startDate, $days, 80000, 150000);
getFile($startDate, $days, 150000, 300000); getFile($startDate, $days, 150000, 300000);
getFile($startDate, $days, 300000, 999999999); getFile($startDate, $days, 300000, 999999999);
} }
if (isset($_REQUEST['split'])) { if (isset($_REQUEST['split'])) {
doSplit($startDate, $days); doSplit($startDate, $days);
} else { } else {
getFile($startDate, $days, "" , ""); getFile($startDate, $days, "" , "");
} }
  }
?> ?>
   
<?php  
include_once("../lib/common.inc.php");  
 
$active = Array('0EC8D805-C293-3ADD-E51A93667D977314|Administrative Appeals Tribunal','0ECAA17D-9862-5309-101D94A126495C7F|Aged Care Standards and Accreditation Agency Ltd','CE45735B-F9FC-04DA-F299C730D9BE613E|Airservices Australia','0EC8DF71-ED98-8593-2D776EE93D9BA248|Attorney-General\'s Department','0ECA6B4C-DE4F-A04A-DBFB5F39B050B6D7|AusAid','0ECA6F64-F6B8-F406-E490A1479A7A717B|Austrade','D2724D99-F230-A93A-93D62A8DCC187940|Australia Council for the Arts','D26C4D0A-FF6E-612A-C6FEDB2D5E71AE4A|Australian Antarctic Division','C8E854CD-E966-9A35-078FF6702EC1ECED|Australian Broadcasting Corporation','0ECB50CF-028A-FB9D-3E5EF0F9708E4BC7|Australian Bureau of Statistics','0ECA671F-EA1F-8560-1D7C90408694B565|Australian Centre for International Agricultural Research','A861A42C-B32C-85A8-0F719005E27F4E23|Australian Commission for Law Enforcement Integrity','C8F9DAF8-9763-EA22-FA44B6BBC12B0B94|Australian Communications and Media Authority (ACMA)','0ECB2BB9-B19C-4929-87EC63542388D079|Australian Competition and Consumer Commission','0EC8E42E-EB6A-15DA-3F001AFB9C2B8D34|Australian Crime Commission','0EC8E8CE-9BCF-0651-D4362CF53DB8E4DC|Australian Customs and Border Protection Service','CD51BCA4-9DC7-9494-B7D944029D03A1F9|Australian Electoral Commission','D248626B-0BDD-B201-1A1C7C978AD973D2|Australian Fair Pay Commission','0EC8EDF3-E025-2F80-AEB39B350641C81F|Australian Federal Police','0EC8B90B-CBF5-8EC4-2C4E261041A25E16|Australian Fisheries Management Authority','0ECABD48-0388-F8AB-00BD4EB12FA44067|Australian Hearing Services','0EC920D5-CEB1-81FC-5A107A206F4A6BF3|Australian Human Rights Commission','D257B064-D245-51CC-F69A50FF4620915B|Australian Industrial Registry','0EC8F7B1-03ED-C4C3-70FBDF105ADB2FB6|Australian Institute of Criminology','D32EC07E-E22E-5805-1240CF68033C5E15|Australian Institute of Family Studies','0ECA9D77-A0B8-448A-53945B4DFACEE685|Australian Institute of Health and Welfare','D31CF0E2-B1A4-DE74-5D7B7B1DC97EA1DC|Australian Institute of Marine Science','0EC8FC41-C1BE-587A-A19920F43BA616BF|Australian Law Reform Commission','CE5DCAA3-D793-2FEE-B3C263B84AF2676C|Australian Maritime Safety Authority','0ECAED96-0B3B-1D24-56412EC3384996B0|Australian National Audit Office (ANAO)','D281D726-938C-D76D-A346348BEFC509F9|Australian National Maritime Museum','D31E738F-F139-2BC2-EBF2764D7812EA10|Australian Nuclear Science and Technology Organisation (ANSTO)','0ECB3D20-C837-FBE2-B1C32937F87CBB8F|Australian Office of Financial Management','82C5CFA1-0088-7B9E-9A3EF95987B55045|Australian Organ and Tissue Donation and Transplantation Authority','0EC8BF2B-B23F-0A07-0659BB9760EFC94E|Australian Pesticides and Veterinary Medicines Authority','0ECB5AFF-F4DC-06E3-97B3118B978F33BD|Australian Prudential Regulation Authority (APRA)','0ECAF18D-044A-0F5E-AD942B0CD5BB1ACC|Australian Public Service Commission','0ECA88C8-B803-ECE2-00F37CE4797C74BC|Australian Radiation Protection and Nuclear Safety Agency (ARPANSA)','D320882B-ED70-8061-6A5B2F8E64D6F575|Australian Research Council','CD5A2434-9592-2217-49970AF89E5956F8|Australian Reward Investment Alliance (ARIA)','0ECB44F1-BC3B-58E0-96CD33517E10E38B|Australian Securities and Investments Commission','0EC9056F-C13F-ED84-07B410D54C4A1013|Australian Security Intelligence Organisation','D303A5DD-B83B-EC45-588E3680B4E842E4|Australian Sports Anti-Doping Authority (ASADA)','0ECB54CA-EE15-8B26-3C430607E8DB3D4E|Australian Taxation Office','0EC900DB-D645-6C40-DD8BEA03CC15D392|Australian Transaction Reports and Analysis Centre (AUSTRAC)','77068F86-0A15-723A-C2FC1601C44FFCD2|Australian Transport Safety Bureau','0EC9AC89-DEB3-1441-2441891A3772863E|Australian War Memorial','D28B4F07-C2F2-2D4F-1C9229D177088373|Bureau of Meteorology','0ECA90FE-A44B-2EAA-08039CC6C43E728D|Cancer Australia','0ECAB1CF-D480-0C8B-70670DFC4FFDAC56|Centrelink','CE608086-A4DC-45F6-1179DCC148CF91F7|Civil Aviation Safety Authority','D24AFCAC-A2B2-4766-17C9A3EC3AAE4205|Comcare','166B9AD2-ACC9-B56F-4D5B47BD325DEB25|Commonwealth Grants Commission','CD5BDE89-9805-D921-0DAAFDBD5312D0D5|Comsuper','0ECB5EF6-CC7B-7C8E-32798557B78F6D98|Corporations and Markets Advisory Committee','0EC909FF-D902-5FD3-6660ADB353470F95|Crimtrac','0ECAC700-BDE8-458D-6A4E91C8B151A270|CRS Australia','D3275762-D634-4459-D33A26E1BEA05D14|CSIRO','0EC99E6C-0375-2DAF-A8338121FCBD6F7A|Defence Housing Australia','0EC9A29C-E478-AD19-3F0F29F6BE4914BF|Defence Materiel Organisation','0EC892FD-E156-BCB0-ADF5D534E584BC18|Department of Agriculture, Fisheries and Forestry','FB2B0C69-0AAF-1B2B-8186EC38772F8FC1|Department of Broadband, Communications and the Digital Economy','69368049-A8EF-0896-EA9C603C856788D9|Department of Climate Change and Energy Efficiency','0EC98EF9-E020-5DA9-DCB10135BE81BD2B|Department of Defence','D23E9B50-DAE3-6701-D90A2582EE48A4DA|Department of Education, Employment and Workplace Relations','D2FBF89C-D43D-4B3E-527132AC0D41ABBB|Department of Families, Housing, Community Services and Indigenous Affairs','CD39DC0D-D4B3-DFEC-DDDCD52E651F06EA|Department of Finance and Deregulation','0ECA5FC9-A4AD-0A3A-97A8DD3FD9D44CB1|Department of Foreign Affairs and Trade','0ECA80C0-EC9F-B5B9-0D3E8A4537C39808|Department of Health and Ageing','0ECAADBC-B488-A53B-F4F6672EC813849A|Department of Human Services','0ECB6A9B-BA91-CB7D-36C62C5C9191D403|Department of Immigration & Citizenship','047091E8-CEE4-A9FF-BF552F538D279807|Department of Infrastructure and Transport','FADB0367-F000-E0B9-8F79FD109F613AB6|Department of Innovation, Industry, Science and Research','0ECB7ED8-BB19-D108-324A8A05B1966ABF|Department of Parliamentary Services','2F03BD8D-F73D-C35C-729559C6C70C6602|Department of Regional Australia, Regional Development and Local Government','FADFD268-9BF5-97E4-2F247B92F74E82C0|Department of Resources, Energy and Tourism','62304115-AA13-68D1-592110A8021DA68E|Department of Sustainability, Environment, Water, Population and Communities','0ECB8490-9B07-1898-98170CDD42A9DFF7|Department of the House of Representatives','0ECAE795-F858-203D-FD1C9FF933EF4A37|Department of the Prime Minister and Cabinet','0ECB8A6E-B354-715B-C9DEDE4A6DA3C393|Department of the Senate','0ECB25C0-02C3-6BAA-4738951514F489A9|Department of the Treasury','0EC9A85E-BA37-0A60-47A828CD70D831FC|Department of Veterans\' Affairs','D2E272D5-DDD0-178B-F1BE5A9181D3ACAE|Director of National Parks','D2F85A2B-E563-118E-0CB302E02C74397C|Equal Opportunity for Women in the Workplace Agency','0ECA73FA-FAAD-62B5-48581DF753E57CCA|Export Finance and Insurance Corporation (EFIC)','A535F827-E58E-89FB-7F58107CBBD0D79A|Fair Work Australia','0EC91301-C770-6470-480E879920826ABD|Family Court of Australia','0EC91799-A81B-262C-CE6ACAB2622F0566|Federal Court of Australia','0EC91C3C-BB6B-97BF-76BEF63DD0905AAF|Federal Magistrates Court','08355C10-AB46-67AA-421E334D1B45E125|Food Standards Australia New Zealand','CD5E362E-A615-1102-67814B74731025AD|Future Fund Management Agency','D33926C6-BB30-4A30-3A29A5821CFB7AE6|Geoscience Australia','0EC8CA07-AE70-7EB2-5A174487D4BD6236|Grains Research and Development Corporation','D2E5D48D-08A4-5CC9-5378FEA3CD8E649C|Great Barrier Reef Marine Park Authority','0EC925CD-F184-26AF-DE8A84DE3CBA3790|Insolvency and Trustee Service Australia (ITSA)','0ECB302F-AADD-2BB1-392F50E0E94CB076|Inspector-General of Taxation','D3174EBA-F3C0-28E6-7A669C23CF0B3040|IP Australia','0ECAB5DF-B75F-EC35-92EA7821EFF77C0D|Medicare Australia','0ECB74A7-BE11-FC3C-8696F7F93D7612C0|Migration Review Tribunal and Refugee Review Tribunal (MRT-RRT)','F8E42DAB-9570-A008-97294775650CCE6E|Murray-Darling Basin Authority','0A18A552-0B56-257B-70BE077385CE2EDC|National Archives of Australia','0ECA8CEA-08C9-6D55-C57A7A102DFFBC8A|National Blood Authority','D2347B3A-F330-0317-68AB0C4F7240B9A5|National Capital Authority','0ECB3416-FEB1-F5E0-FB4760831CA2F66E|National Competition Council','7DEE189B-0A00-07D1-2D1C778EDAEFEF6D|National Film and Sound Archive','D2E7830B-9692-3124-1C2E1D74AAC8FFFF|National Gallery of Australia','0ECA957E-E479-2758-528FA4E576A27A5D|National Health and Medical Research Council','D2EA1497-0BB3-AFBD-76559FA87101FF06|National Library of Australia','D2EC2CF2-FEEE-8FB2-46193EDF8EA2F503|National Museum of Australia','0EC92A40-B2DA-D4FF-16895BCD00F9E20F|National Native Title Tribunal','D33DB6EB-FEE1-F686-7385E65E48749DD2|National Offshore Petroleum Safety Authority','D2EF702D-EF9B-B363-BDA3A4950C5ED57F|National Water Commission','0ECB00AF-04FE-735D-82D0B84D1A19F95A|Office of National Assessments','0EC93653-9FCE-12DD-DAAC73E23DCAE8CA|Office of Parliamentary Counsel','0ECB48E3-9198-6F2C-9737A69F9D15177A|Office of the Auditing and Assurance Standards Board','0ECB4CD6-A6D6-4334-D550948337CE9F56|Office of the Australian Accounting Standards Board','D25ACD14-ABA3-F69F-E1ADA4503ED97C82|Office of the Australian Building and Construction Commissioner (ABCC)','D331236A-BDE0-5CD7-24EF78F052CB2B50|Office of the Australian Information Commissioner','0ECAF6CA-ACBE-E3E7-6DCBF175E012F817|Office of the Commonwealth Ombudsman','0EC93B4D-DC77-6FA0-7E15530A7D7344CB|Office of the Director of Public Prosecutions','39DCC587-FF78-8759-E91BF5B9EC3D1904|Office of the Fair Work Ombudsman','0ECB049D-B7DC-1697-586AB4455B0DF251|Office of the Inspector-General of Intelligence and Security','0ECB0887-D30E-E490-3F16BCB7EF406D8E|Office of the Official Secretary to the Governor-General','E0EAE43E-B918-12DC-9F4E0E03811CACAD|Office of the Renewable Energy Regulator','D726F8EA-D648-B4DF-E25FF1EEE68C9700|Old Parliament House','87A575EB-E6CE-7E8B-1CB3D9B6580FAE5B|Private Health Insurance Ombudsman','0ECB380B-FC93-8003-9A1F04BD55A10F62|Productivity Commission','0ECA9978-D7C8-3F44-2D21C2827407BEF5|Professional Services Review','0ECB64C5-E6E4-3D23-B4409B18EB609B25|Reserve Bank of Australia','0ECB4106-02BC-64C6-1DF8032E549D88E4|Royal Australian Mint','4A350604-FD8E-C7BB-D6C6A14AEE6D8873|Safe Work Australia','D25D96A7-B9B7-21D2-57AA60EAC138107B|Seacare','D2FF2257-0E69-4B7C-FCF6AB672ECC341C|Social Security Appeals Tribunal','D2F16C5B-BCFB-E14D-9B62DEEDF992798B|Sydney Harbour Federation Trust','0ECA84C7-D6C3-3299-9F898B9C201D771B|Therapeutic Goods Administration','D340FD88-0AFE-B091-1F43D9EDBCE164D4|Tourism Australia','EB74EB82-AA02-F70B-DC648859ABFC28DA|Wheat Exports Australia');  
 
$suspended = Array('8B346DD0-D9A5-585C-1B3174A9B6292AD1|Aboriginal and Torres Strait Islander Services','0ECB16D3-9684-471C-3FFBCCCAB63728B4|Airservices Australia','0EC975AC-F94D-B8B5-FDF5CF053D78F7EA|Australia Council for the Arts','0ECA7934-9725-0D31-1BD08C6ADFD16040|Australia-Japan Foundation','0ECA043A-C02D-1838-E994DF3EC8B0A857|Australian Antarctic Division','0EC96B6B-9A30-F9E4-892DA6860B3985B2|Australian Broadcasting Corporation','0EC9521F-C38A-2FB1-54CEF555CE76807A|Australian Communications and Media Authority (ACMA)','0ECA48E7-B536-E530-CA1F4F8A4056517F|Australian Electoral Commission','0EC9D8CD-D6F8-A695-854B714011D9B2E8|Australian Fair Pay Commission','0EC9703D-9C88-C7FF-E15390103B51CE22|Australian Film Commission','D27DB409-E5C9-15AD-635A70CEF5A8E05C|Australian Film Commission','0EC96705-AED6-462D-E1579FE99DD57511|Australian Film Television and Radio School','D27F93E1-9898-8ED5-5DF9628A1CE78BBF|Australian Film Television and Radio School','0EC9DCED-ED0B-FF25-20323EF5E93EC88E|Australian Industrial Registry','0EC9BF9B-C83C-4EC5-DDE3C845EBF3CCC0|Australian Institute of Aboriginal and Torres Strait Islander Studies (AIATSIS)','D246AE91-0DD2-193E-84F9A3E13664E58E|Australian Institute of Aboriginal and Torres Strait Islander Studies (AIATSIS)','0ECA2851-AD46-9261-B3A77D28C5CC1351|Australian Institute of Family Studies','0EC9BB58-BBA8-3F3D-AD04CBFE4FABC85D|Australian Institute of Marine Science','0ECB1ACC-FAAC-3895-9EC179BC71C3FC54|Australian Maritime Safety Authority','0EC9611A-C5D2-43B5-D4039EED991272E3|Australian National Maritime Museum','0EC9C3D2-CE1C-8C81-085ADA97E2172420|Australian Nuclear Science and Technology Organisation (ANSTO)','0EC9B71F-EDBC-5E42-E44D5595BDF7B3F4|Australian Research Council','0ECA59B7-D4C6-360D-4829CB8A5E15B664|Australian Reward Investment Alliance (ARIA)','0EC95958-08E9-4A16-A79AC1CB828B9535|Australian Sports Anti-Doping Authority (ASADA)','0EC8C3DE-B6EB-88B8-0FD9460AC543DD0C|Biosecurity Australia','0ECA1921-EA6F-1BE2-3E85DBF7BBCDE734|Bureau of Meteorology','0ECAC142-B8B8-CCE0-A4B00E4B67ED0DCB|Child Support Agency','0ECB1FED-D2C6-6214-2CEB31CE9B107ED1|Civil Aviation Safety Authority','0EC9D499-F2DE-F8D9-0239ACA17C2ABFBB|Comcare','0ECA55A3-A0B2-0D36-D383E6A113AD5749|Commonwealth Grants Commission','0ECA4CF9-9312-2F3D-637C98CF2FEEB5A4|Comsuper','0EC9C7FE-F7AC-09BD-3C498B63A9DDDDA4|CSIRO','0EC8B354-F006-A824-A43120384BE56A98|Dairy Adjustment Authority','D3328CCE-DEA4-5516-AA23F77F557454FC|Department of Climate Change','0EC94B72-AD24-B695-3C5C388FBC0C23AA|Department of Communications, Information Technology and the Arts','0EC9B2BB-D5C8-8061-8CC999143D0D291C|Department of Education, Science and Training','0EC9CE2C-A998-C45A-90697489AC42B83B|Department of Employment and Workplace Relations','0ECA21F5-F5FE-7F08-52CD6FFB54E788FE|Department of Families, Community Services & Indigenous Affairs','0ECA32E7-E860-DFD4-0FBDCE1CC8E0FC84|Department of Finance and Administration','8B3539BA-EC97-7510-AF049F389DC0497A|Department of Immigration and Multicultural Affairs','8B361B4A-EAAE-D747-134D9FA97497C70F|Department of Immigration and Multicultural and Indigenous Affairs (DIMIA)','0ECACF65-D93B-D892-1862B65F15C92A6A|Department of Industry, Tourism and Resources','CE419954-CB32-1154-9E61EDB5805C222D|Department of Infrastructure, Transport, Regional Development and Local Government','0EC9F8FB-F224-1E70-F59834C1D5CE12D5|Department of the Environment and Water Resources','D2DFCF42-A87B-181C-2F48D7EEE8849AFD|Department of the Environment, Water, Heritage and the Arts','0ECB0EE4-9D78-A341-363B0D13161C5916|Department of Transport and Regional Services','0ECA0863-0F4E-5FA8-B7C522D16CCAC9BB|Director of National Parks','0EC90E81-DAF0-F67A-7FDC1AE664FF0BEE|Emergency Management Australia','0EC9E429-9FFF-7E05-41ADCC29FE17811C|Equal Opportunity for Women in the Workplace Agency','576FCE5F-E258-4A5C-92C11639C73A0442|Export Wheat Commission','0ECA518C-EF07-86F5-ADCAA84198009116|Future Fund Management Agency','0ECAE1C5-E249-022B-DCC7D944F398E1FD|Geoscience Australia','0ECA0CF1-AEF7-5C78-23878C6A5BF93C36|Great Barrier Reef Marine Park Authority','0ECADD52-F400-97E8-25F98B9FF96FFD08|IP Australia','0EC8D025-D94D-FF1D-97130B40320BAD9A|Land and Water Australia','0EC98433-EB5E-BEB1-1EEC7CADF83918A0|National Archives of Australia','CD603E31-CD1F-AAE5-F233F954A031553E|National Archives of Australia','0ECB12DC-BF41-FF5B-CB306CF040EC3218|National Capital Authority','0EC97A03-EA2E-5AE3-EC3C2C23487ECECA|National Gallery of Australia','0EC98880-F5F1-6560-605A0250EA58D139|National Library of Australia','0EC97FE7-E894-67B2-A8CE40DEF409AC23|National Museum of Australia','0ECAD957-B214-674F-3C94DEEF52BA3F46|National Offshore Petroleum Safety Authority','0ECAFC83-0B5D-045A-EE43EA12B9953CC0|National Water Commission','48499BD1-AFE0-1093-EF06293D78B3FD65|National Water Commission','0EC92FD3-F7B3-B0E0-9A8D8D2B611BB615|Office of Film and Literature Classification','0EC9E84A-A9F7-4EEF-5DDD2FC87C1F1B55|Office of the Australian Building and Construction Commissioner (ABCC)','0EC940DD-9A7E-1ECD-B44DDA0B72B2407F|Office of the Privacy Commissioner','0ECA10FE-AC03-80D8-C8DF1069C707351E|Office of the Renewable Energy Regulator','D3362537-FE00-1892-B408CABF5E0257A7|Office of the Renewable Energy Regulator','0EC9F2EC-C778-46D0-F15FDB1A8F1552F9|Office of Workplace Services','FB2A3EA0-D6FC-DB1D-19B0B72180A8A19B|Questacon','D329A60A-E914-FB37-FBA853A4CE8558EB|Questacon','0ECB788C-CC5C-2969-4B94EFB3913B0E65|Refugee Review Tribunal','A2A6EBF4-A8F5-E60B-5C25ACD3EA0679D8|Screen Australia','0EC9EC88-9B12-CB63-56A58BE69BDF3B6F|Seacare','0ECA2CE0-CBA9-9E13-AA0FB347CF4B5FD1|Social Security Appeals Tribunal','0ECA1510-B4A2-BBA4-D6FDE37DFAAC7C12|Sydney Harbour Federation Trust','0ECAA587-C851-4038-8CDC9CCE9A28F6E6|The National Institute of Clinical Studies Ltd','0ECAD567-E1E7-F5FC-72BA34FDF72F0FC0|Tourism Australia','7A592345-0410-DF1C-4B349EA35F314D3F|Workplace Authority','003B8DE1-D09A-D72F-28CEBC19DB84E866|Workplace Ombudsman','D260B27E-9744-EF72-C065072F24B4A62A|Workplace Ombudsman');  
 
foreach ($active as $agency ) {  
$agencyParts = explode("|",$agency);  
$agency = $agencyParts[1];  
$agencyInsert = "INSERT INTO agency (agencyName) VALUES ('$agency')";  
$result = mysql_query($agencyInsert);  
$result = mysql_query("UPDATE agency SET status = 'active' where agencyName = '".mysql_real_escape_string($agency)."';") ;  
if ($result) echo $agency. " set to active in ". mysql_affected_rows() . " divisions/branches <br>\n";  
else echo "error".mysql_error();  
}  
foreach ($suspended as $agency) {  
$agencyParts = explode("|",$agency);  
$agency = $agencyParts[1];  
$agencyInsert = "INSERT INTO agency (agencyName) VALUES ('$agency')";  
$result = mysql_query($agencyInsert);  
$result = mysql_query("UPDATE agency SET status = 'suspended' where agencyName = '".mysql_real_escape_string($agency)."';") ;  
if ($result) echo $agency. " set to suspended in ". mysql_affected_rows() . " divisions/branches <br>\n";  
else echo "error".mysql_error();  
}  
?>  
<?php  
include_once ("../lib/common.inc.php");  
// to reset: update agency set abn = 0, website = ''  
$ch = curl_init();  
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  
curl_setopt($ch, CURLOPT_REFERER, "http://contractdashboard.lambdacomplex.org");  
$querySel = sprintf("SELECT * FROM `agency` where ABN = 0 OR website = ''");  
$resultSel = mysql_query($querySel);  
while ($row = mysql_fetch_array($resultSel, MYSQL_ASSOC)) {  
$agency = $row['agencyName'];  
//foreach $agency  
$url = "http://ajax.googleapis.com/ajax/services/search/web?v=1.0&key=ABQIAAAA95XYXN0cki3Yj_Sb71CFvBSgIPe2k9-DRgEVQvbvQDV8xmTiXRTBpHxrD7bSh5rl2lswY56769CyQQ&rsz=small&filter=1&gl=au&q=" . urlencode($agency) . "%20ABN%20site:.gov.au%20-site:www.abr.business.gov.au";  
curl_setopt($ch, CURLOPT_URL, $url);  
$body = curl_exec($ch);  
$json = json_decode($body);  
echo "<pre>";  
$result = $json->responseData->results[0];  
print_r($result);  
echo "</pre>";  
echo "<b> Agency:</b> $agency";  
echo "<b> URL:</b> http://" . $result->visibleUrl;  
preg_match('/\d{2} \d{3} \d{3} \d{3}/i', $result->content, $abn);  
$abn[0] = str_replace(" ","",$abn[0]);  
echo "<b> ABN:</b> {$abn[0]}";  
if ($abn[0] > 1000) {  
$result = mysql_query("UPDATE agency SET website = 'http://" . $result->visibleUrl . "', abn = '{$abn[0]}' WHERE agencyName = '$agency';");  
if ($result) echo $agency . " set in " . mysql_affected_rows() . " <br>\n";  
} else {  
 
echo "invalid ABN";  
$result = mysql_query("UPDATE agency SET website = 'http://" . $result->visibleUrl . "' WHERE agencyName = '$agency';");  
if ($result) echo $agency . " set in " . mysql_affected_rows() . " <br>\n";  
}  
// fi  
 
}  
curl_close($ch);  
?>  
<?php <?php
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
if ($_REQUEST['agency']) { if ($_REQUEST['agency']) {
include_header("Agency");  
$agency = htmlentities(strip_tags($_REQUEST['agency'])); $agency = htmlentities(strip_tags($_REQUEST['agency']));
MethodCountGraph($agency); include_header($agency);
CnCGraph($agency); echo '<center><h1>'.$agency.'</h1></center>';
MethodValueGraph($agency); // MethodCountGraph($agency);
  // CnCGraph($agency);
  // MethodValueGraph($agency);
/* biggest contracts /* biggest contracts
spending by year spending by year
spending by industry/category spending by industry/category
spending by supplier spending by supplier
spread procurement methods (stacked bar graph) spread procurement methods (stacked bar graph)
+ percent consultancies + percent confidential (bar graph) + percent consultancies + percent confidential (bar graph)
Average value by procurement type Average value by procurement type
--- info --- info
website, procurement plan, annual reports website, procurement plan, annual reports
Breakdown of divisions/branches Breakdown of divisions/branches
Breakdown percentage,number,value by procurement type Breakdown percentage,number,value by procurement type
Histograph, overlaying number value reported per week over X years Histograph, overlaying number value reported per week over X years
Compliance statistics: amendments, delay in reporting average and number completely late */ Compliance statistics: amendments, delay in reporting average and number completely late */
$query = 'SELECT "CNID", "description", "value", "agencyName", "category", $query = 'SELECT "CNID", "description", "value", "agencyName", "category",
"contractStart", "supplierName" "contractStart", "supplierName"
FROM contractnotice FROM contractnotice
WHERE "agencyName" = :agency WHERE "agencyName" = :agency
ORDER BY "value" DESC'; ORDER BY "value" DESC limit 100';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":agency", $agency); $query->bindParam(":agency", $agency);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
echo "<table> <thead> echo "<table> <thead>
<tr> <tr>
<th>Contract Notice Number</th> <th>Contract Notice Number</th>
<th>Contract Description</th> <th>Contract Description</th>
<th>Total Contract Value</th> <th>Total Contract Value</th>
<th>Agency</th> <th>Agency</th>
<th>Contract Start Date</th> <th>Contract Start Date</th>
<th>Supplier</th> <th>Supplier</th>
</tr> </tr>
</thead>"; </thead>";
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row['value']), 2); $value = number_format(doubleval($row['value']), 2);
echo ("<tr> echo ("<tr>
<td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td> <td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td>
<td><b>{$row['description']}</b></a></td> <td><b>{$row['description']}</b></a></td>
<td>\$$value</td><td>{$row['agencyName']}</td> <td>\$$value</td><td>{$row['agencyName']}</td>
<td>{$row['contractStart']}</td> <td>{$row['contractStart']}</td>
<td>{$row['supplierName']}</td> <td>{$row['supplierName']}</td>
</tr>"); </tr>");
} }
echo "</table>"; echo "</table>";
} else { } else {
/* /*
split by portfolio split by portfolio
*/ */
include_header("Agencies"); include_header("Agencies");
agenciesGraph(); agenciesGraph();
$query = 'SELECT SUM("value"), "agencyName" $query = 'SELECT SUM("value"), "agencyName"
FROM contractnotice FROM contractnotice
WHERE "childCN" is null WHERE "childCN" is null
GROUP BY "agencyName" '; GROUP BY "agencyName" ';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
echo "<table> <thead> echo "<table> <thead>
<tr> <tr>
<th>Agency</th> <th>Agency</th>
<th>Total Contracts Value</th> <th>Total Contracts Value</th>
</tr> </tr>
</thead>"; </thead>";
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row[0]), 2); $value = number_format(doubleval($row[0]), 2);
$agency = stripslashes($row[1]); $agency = stripslashes($row[1]);
echo ("<tr><td><b><a href=\"displayAgency.php?agency={$agency}\">{$agency}</a></b></td><td>\$$value</td></tr>\n"); echo ("<tr><td><b><a href=\"displayAgency.php?agency={$agency}\">{$agency}</a></b></td><td>\$$value</td></tr>\n");
} }
echo "</table>"; echo "</table>";
} }
include_footer(); include_footer();
?> ?>
   
<?php <?php
include_once("./lib/common.inc.php"); include_once("./lib/common.inc.php");
include_header("Contract");  
$query = 'SELECT * $query = 'SELECT *
FROM contractnotice FROM contractnotice
WHERE "CNID" = :CNID LIMIT 1'; WHERE "CNID" = :CNID LIMIT 1';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->bindParam(":CNID", $_REQUEST['CNID']); $query->bindParam(":CNID", $_REQUEST['CNID']);
$query->execute(); $query->execute();
  $contractResult = $query->fetch(PDO::FETCH_ASSOC);
  if (!$contractResult) {
  header("Status: 404 Not Found");
  header("HTTP/1.0 404 Not Found");
  include_header("Contract Not Found");
  echo "<center><h1>No Contract Notice with that ID found</h1></center>";
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll(PDO::FETCH_ASSOC) as $row) { } else {
  $description = ucsmart($contractResult["description"]);
  include_header($description);
  echo '<center><h1>'.$description.'</h1></center>';
  databaseError($conn->errorInfo());
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
foreach (array_filter($row) as $key => $value) { foreach (array_filter($contractResult) as $key => $value) {
echo "<b>$key</b>&nbsp;"; echo "<b>$key</b>&nbsp;";
switch ($key) { switch ($key) {
case "supplierName": case "supplierName":
case "supplierABN": case "supplierABN":
echo '<a href="displaySupplier.php?supplier=' . $row['supplierABN'] . '-' . urlencode($row['supplierName']) . '">' . $value . "</a>"; echo '<a href="displaySupplier.php?supplier=' . $contractResult['supplierABN'] . '-' . urlencode($contractResult['supplierName']) . '">' . $value . "</a>";
break; break;
case "agencyName": case "agencyName":
echo '<a href="displayAgency.php?agency=' . urlencode($value) . '">' . $value . "</a>"; echo '<a href="displayAgency.php?agency=' . urlencode($value) . '">' . $value . "</a>";
break; break;
case "value": case "value":
echo "$" . number_format(doubleval($value), 2); echo "$" . number_format(doubleval($value), 2);
break; break;
default: default:
echo str_replace(" ", "<br>", $value); echo str_replace(" ", "<br>", ucsmart($value));
} }
echo "<br>"; echo "<br>";
} }
}  
echo '<br><a href="https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN' . $_REQUEST['CNID'] . '"> View original record @ tenders.gov.au</a><br>'; echo '<br><a href="https://www.tenders.gov.au/?event=public.advancedsearch.keyword&keyword=CN' . $_REQUEST['CNID'] . '"> View original record @ tenders.gov.au</a><br>';
$query = 'SELECT * FROM `heuristic_results` where "CNID" = :CNID'; $query = 'SELECT * FROM heuristic_results where "CNID" = :CNID';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$agencyName = $input . '%'; $agencyName = $input . '%';
$query->bindParam(":CNID", $_REQUEST['CNID']); $query->bindParam(":CNID", $_REQUEST['CNID']);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll() as $r) { foreach ($query->fetchAll() as $r) {
echo "<b>{$r['heuristic_name']}</b>: {$r['heuristic_value']} (raw value: {$r['raw_value']}, mean: {$r['mean']}, stddev: {$r['stddev']})<br>"; echo "<b>{$r['heuristic_name']}</b>: {$r['heuristic_value']} (raw value: {$r['raw_value']}, mean: {$r['mean']}, stddev: {$r['stddev']})<br>";
} }
  }
include_footer(); include_footer();
?> ?>
   
<?php <?php
   
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
if ($_REQUEST['supplier']) { if ($_REQUEST['supplier']) {
   
include_header("Supplier");  
$supplierS = htmlentities(strip_tags($_REQUEST['supplier'])); $supplierS = htmlentities(strip_tags($_REQUEST['supplier']));
  include_header(str_replace("%","",$supplierName));
  echo '<center><h1>'.str_replace("%","",$supplierName).'</h1></center>';
   
// MethodCountGraph($supplierS); // MethodCountGraph($supplierS);
// CnCGraph($supplierS); // CnCGraph($supplierS);
// MethodValueGraph($supplierS); // MethodValueGraph($supplierS);
/* lobbyist ties /* lobbyist ties
   
links to ABR/ASIC/Google News/ASX/Court records links to ABR/ASIC/Google News/ASX/Court records
   
total value to various agencies (bar graph) total value to various agencies (bar graph)
   
spread procurement methods + percent consultancies + percent confidential (bar graph) spread procurement methods + percent consultancies + percent confidential (bar graph)
   
spread of contract values spread of contract values
   
spread of industries (textual?) */ spread of industries (textual?) */
$query = 'SELECT "CNID", "description", "value", "agencyName", "category", $query = 'SELECT "CNID", "description", "value", "agencyName", "category",
"contractStart", "supplierName" "contractStart", "supplierName"
FROM contractnotice WHERE ' . FROM contractnotice WHERE ' .
$supplierQ . ' ' . $standardQ $supplierQ . ' ' . $standardQ
. ' ORDER BY value DESC'; . ' ORDER BY value DESC';
echo $query; echo $query;
$query = $conn->prepare($query); $query = $conn->prepare($query);
   
   
if ($supplierParts[0] > 0) { if ($supplierParts[0] > 0) {
$query->bindParam(":supplierABN", $supplierABN); $query->bindParam(":supplierABN", $supplierABN);
} else { } else {
$query->bindParam(":supplierName", $supplierName); $query->bindParam(":supplierName", $supplierName);
} }
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
// echo '<img src="graphs/displayMethodCountGraph.php?month=' . stripslashes($supplier) . '">'; // echo '<img src="graphs/displayMethodCountGraph.php?month=' . stripslashes($supplier) . '">';
// echo '<img src="graphs/displayCnCGraph.php?month=' . stripslashes($supplier) . '">'; // echo '<img src="graphs/displayCnCGraph.php?month=' . stripslashes($supplier) . '">';
   
echo "<table> <thead> echo "<table> <thead>
<tr> <tr>
<th>Contract Notice Number</th> <th>Contract Notice Number</th>
<th>Contract Description</th> <th>Contract Description</th>
<th>Total Contract Value</th> <th>Total Contract Value</th>
<th>Agency</th> <th>Agency</th>
<th>Contract Start Date</th> <th>Contract Start Date</th>
<th>Supplier</th> <th>Supplier</th>
</tr> </tr>
</thead>"; </thead>";
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row['value']), 2); $value = number_format(doubleval($row['value']), 2);
echo ("<tr> echo ("<tr>
<td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td> <td><a href=\"displayContract.php?CNID={$row['CNID']}\">{$row['CNID']}</a></td>
<td><b>{$row['description']}</b></a></td> <td><b>{$row['description']}</b></a></td>
<td>\$$value</td><td>{$row['agencyName']}</td> <td>\$$value</td><td>{$row['agencyName']}</td>
<td>{$row['contractStart']}</td> <td>{$row['contractStart']}</td>
<td>{$row['supplierName']}</td> <td>{$row['supplierName']}</td>
</tr>"); </tr>");
} }
echo "</table>"; echo "</table>";
} else { } else {
/* /*
histograph of supplier size/value histograph of supplier size/value
*/ */
include_header("Suppliers"); include_header("Suppliers");
suppliersGraph(); suppliersGraph();
$query = 'SELECT SUM("value") as val, MAX("supplierName") as supplierName, "supplierABN",( $query = 'SELECT SUM("value") as val, MAX("supplierName") as supplierName, "supplierABN",(
case when "supplierABN" != 0 THEN "supplierABN"::text ELSE "supplierName" END) as supplierID case when "supplierABN" != 0 THEN "supplierABN"::text ELSE "supplierName" END) as supplierID
FROM contractnotice FROM contractnotice
WHERE "childCN" is null WHERE "childCN" is null
GROUP BY supplierID,"supplierABN" GROUP BY supplierID,"supplierABN"
ORDER BY val DESC ORDER BY val DESC
LIMIT 100'; LIMIT 100';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
echo "<table> <thead> echo "<table> <thead>
<tr> <tr>
<th>Position</th> <th>Position</th>
<th>Supplier</th> <th>Supplier</th>
<th>Total Contract Value</th> <th>Total Contract Value</th>
</tr> </tr>
</thead>"; </thead>";
$i = 1; $i = 1;
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
setlocale(LC_MONETARY, 'en_US'); setlocale(LC_MONETARY, 'en_US');
$value = number_format(doubleval($row['val']), 2); $value = number_format(doubleval($row['val']), 2);
$supplier = stripslashes($row['supplierABN'] . '-' . $row['suppliername']); $supplier = stripslashes($row['supplierABN'] . '-' . $row['suppliername']);
echo ("<tr><td>$i</td><td><b><a href=\"displaySupplier.php?supplier={$supplier}\">" . ucsmart($row['suppliername']) . "</a></b></td><td>\$$value</td></tr>\n"); echo ("<tr><td>$i</td><td><b><a href=\"displaySupplier.php?supplier={$supplier}\">" . ucsmart($row['suppliername']) . "</a></b></td><td>\$$value</td></tr>\n");
$i++; $i++;
} }
echo "</table>"; echo "</table>";
} }
include_footer(); include_footer();
?> ?>
   
file:a/futureindex.php (deleted)
<?php  
include_once ("./lib/common.inc.php");  
include_header("Home");  
echo ' <div class="hero-unit">  
<h1>Hello, world!</h1>  
<p>Vestibulum id ligula porta felis euismod semper. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.</p>  
<p><a class="btn primary large">Learn more &raquo;</a></p>  
</div>';  
include_footer();  
?>  
 
 
  google-site-verification: google676a414ad086cefb.html
 
<?php <?php
/* all /* all
SELECT description, count(*) as count SELECT description, count(*) as count
FROM `contractnotice` FROM contractnotice
group by description having count > 1 order by count group by description having count > 1 order by count
*/ */
/*- duplicated description /*- duplicated description
- most duplicated overall, most duplicated per agency/category/supplier etc. */ - most duplicated overall, most duplicated per agency/category/supplier etc. */
$heuristics["METADATA_DUPLICATED_DESCRIPTION"] = Array( $heuristics["METADATA_DUPLICATED_DESCRIPTION"] = Array(
"description" => "" "description" => ""
); );
function METADATA_DUPLICATED_DESCRIPTION($cn) function METADATA_DUPLICATED_DESCRIPTION($cn)
{ {
$averageDuplicatedDescriptions = getAverageDuplicatedDescriptions(); $averageDuplicatedDescriptions = getAverageDuplicatedDescriptions();
$stddevDuplicatedDescriptions = getstddevDuplicatedDescriptions(); $stddevDuplicatedDescriptions = getstddevDuplicatedDescriptions();
$query = 'select count(*) from contractnotice where description = "' . $agencyName . '"'; $query = 'select count(*) from contractnotice where description = "' . $agencyName . '"';
$result = $conn->query($query); $result = $conn->query($query);
$r = $result->fetch(PDO::FETCH_BOTH); $r = $result->fetch(PDO::FETCH_BOTH);
$dupeDesc = $r[0]; $dupeDesc = $r[0];
if ($dupeDesc == 1) $value = 0; if ($dupeDesc == 1) $value = 0;
else $value = abs($dupeDesc - $averageDuplicatedDescriptions) / $stddevDuplicatedDescriptions; else $value = abs($dupeDesc - $averageDuplicatedDescriptions) / $stddevDuplicatedDescriptions;
return Array( return Array(
"heuristic_value" => $value, "heuristic_value" => $value,
"raw_value" => $dupeDesc, "raw_value" => $dupeDesc,
"mean" => $averageDuplicatedDescriptions, "mean" => $averageDuplicatedDescriptions,
"stddev" => $stddevDuplicatedDescriptions "stddev" => $stddevDuplicatedDescriptions
); );
} }
$averageDuplicatedDescriptions; $averageDuplicatedDescriptions;
function getAverageDuplicatedDescriptions() function getAverageDuplicatedDescriptions()
{ {
global $averageDuplicatedDescriptions; global $averageDuplicatedDescriptions;
if (!$averageDuplicatedDescriptions) { if (!$averageDuplicatedDescriptions) {
getStatsDuplicatedDescriptions(); getStatsDuplicatedDescriptions();
} }
return $averageDuplicatedDescriptions; return $averageDuplicatedDescriptions;
} }
$stddevDuplicatedDescriptions; $stddevDuplicatedDescriptions;
function getstddevDuplicatedDescriptions() function getstddevDuplicatedDescriptions()
{ {
global $stddevDuplicatedDescriptions; global $stddevDuplicatedDescriptions;
if (!$stddevDuplicatedDescriptions) { if (!$stddevDuplicatedDescriptions) {
getStatsDuplicatedDescriptions(); getStatsDuplicatedDescriptions();
} }
return $stddevDuplicatedDescriptions; return $stddevDuplicatedDescriptions;
} }
function getStatsDuplicatedDescriptions() function getStatsDuplicatedDescriptions()
{ {
$query = "select avg(count),STDDEV(count) from ( $query = "select avg(count),STDDEV(count) from (
SELECT description, count(*) as count SELECT description, count(*) as count
FROM `contractnotice` FROM contractnotice
group by description having count > 1 group by description having count > 1
) as a;"; ) as a;";
$result = $conn->query($query); $result = $conn->query($query);
$r = $result->fetch(PDO::FETCH_BOTH); $r = $result->fetch(PDO::FETCH_BOTH);
$averageDuplicatedDescriptions = $r[0]; $averageDuplicatedDescriptions = $r[0];
$stddevDuplicatedDescriptions = $r[1]; $stddevDuplicatedDescriptions = $r[1];
} }
   
<?php <?php
  if (php_sapi_name() != "cli") {
   
  include_once ("../lib/common.inc.php");
  auth();
include_once("heuristics.inc.php"); include_once("heuristics.inc.php");
   
$query = 'SELECT *, agency.abn as "agencyABN", case when "supplierABN" != 0 then "supplierABN"::text else "supplierName" end as "supplierID" $query = 'SELECT *, agency.abn as "agencyABN", case when "supplierABN" != 0 then "supplierABN"::text else "supplierName" end as "supplierID"
FROM contractnotice JOIN agency ON contractnotice."agencyName"=agency."agencyName" FROM contractnotice JOIN agency ON contractnotice."agencyName"=agency."agencyName"
WHERE DATE("importDate") = (select * from (SELECT DATE("importDate") WHERE DATE("importDate") = (select * from (SELECT DATE("importDate")
FROM contractnotice ORDER BY "importDate" DESC limit 1) alias) limit 10'; FROM contractnotice ORDER BY "importDate" DESC limit 1) alias) limit 10';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll() as $cn) { foreach ($query->fetchAll() as $cn) {
//get each new CN from latest update //get each new CN from latest update
foreach ($heuristics as $heuristic => $description) { foreach ($heuristics as $heuristic => $description) {
// run all heuristics // run all heuristics
runHeuristic($heuristic, $cn); runHeuristic($heuristic, $cn);
} }
flush(); flush();
} }
/*foreach agency /*foreach agency
   
aggregate agency metrics aggregate agency metrics
   
foreach supplier foreach supplier
   
aggreate supplier metrics aggreate supplier metrics
   
foreach CN foreach CN
   
aggregate CN metrics */ aggregate CN metrics */
  }
?> ?>
   
<?php <?php
   
/*// most interesting /*// most interesting
SELECT sum(heuristic_value) as sum, CNID SELECT sum(heuristic_value) as sum, CNID
FROM `heuristic_results` group by CNID order by sum DESC limit 30 FROM heuristic_results group by CNID order by sum DESC limit 30
   
// spread of values // spread of values
select floor(sum) as val,count(*) from (SELECT sum(heuristic_value) select floor(sum) as val,count(*) from (SELECT sum(heuristic_value)
as sum FROM heuristic_results group by CNID) as a group by val*/ as sum FROM heuristic_results group by CNID) as a group by val*/
   
$series = Array(); $series = Array();
   
include_once("../lib/common.inc.php"); include_once("../lib/common.inc.php");
$query = "select heuristic_name, floor(heuristic_value) as val,count(*) from heuristic_results group by heuristic_name, val"; $query = "select heuristic_name, floor(heuristic_value) as val,count(*) from heuristic_results group by heuristic_name, val";
$result = $conn->query($query); $result = $conn->query($query);
foreach ($result->fetchAll() as $r) { foreach ($result->fetchAll() as $r) {
$series[$r["heuristic_name"]][$r["val"]] = $r[2]; $series[$r["heuristic_name"]][$r["val"]] = $r[2];
} }
   
?> ?>
file:b/index.php (new)
  <?php
  include_once ("./lib/common.inc.php");
  include_header("Home");
  echo ' <div class="hero-unit">
  <h1>Hello, world!</h1>
  <p>Vestibulum id ligula porta felis euismod semper. Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.</p>
  <p><a class="btn primary large">Learn more &raquo;</a></p>
  </div>';
  include_footer();
  ?>
 
 
<?php <?php
date_default_timezone_set("Australia/ACT"); date_default_timezone_set("Australia/ACT");
error_reporting(E_ALL ^ E_NOTICE); error_reporting(E_ALL ^ E_NOTICE);
$conn = new PDO("pgsql:dbname=contractDashboard;user=postgres;password=snmc;host=localhost"); $conn = new PDO("pgsql:dbname=contractDashboard;user=postgres;password=snmc;host=localhost");
if (!$conn) { if (!$conn) {
die("A database error occurred.\n"); die("A database error occurred.\n");
  }
   
  define('ROOT', pathinfo(__FILE__, PATHINFO_DIRNAME));
  if (strstr($_SERVER['PHP_SELF'], "labs/")) {
  $basePath = "../";
  }
   
  require ROOT . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'lib' . DIRECTORY_SEPARATOR . 'openid.php';
  $openid = new LightOpenID($_SERVER['HTTP_HOST']);
   
  function login() {
  global $openid;
  if (!$openid->mode) {
  $openid->required = array('contact/email');
  $openid->identity = 'https://www.google.com/accounts/o8/id';
  header('Location: ' . $openid->authUrl());
  }
  }
   
  function auth() {
  global $openid;
  if ($_SESSION['authed'] == true) {
  return true;
  }
   
  if ($openid->mode) {
  $attr = $openid->getAttributes();
  if ($attr['contact/email'] != 'maxious@gmail.com') {
  die('Access Denied');
  } else {
  $_SESSION['authed'] = true;
  }
  } else {
  login();
  }
} }
// $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
function databaseError($errMsg) { function databaseError($errMsg) {
if ($errMsg[2] != "") { if ($errMsg[2] != "") {
echo '<div class="alert-message error">'; echo '<div class="alert-message error">';
die(print_r($errMsg, true)); die(print_r($errMsg, true));
echo "</div>"; echo "</div>";
} }
} }
function ucsmart($str) { function ucsmart($str) {
$shortWords = Array("The", "Pty", "Ltd", "Inc", "Red", "Oil", "A", "An", "And", "At", "For", "In" $shortWords = Array("The", "Pty", "Ltd", "Inc", "Red", "Oil", "A", "An", "And", "At", "For", "In"
, "Of", "On", "Or", "The", "To", "With"); , "Of", "On", "Or", "The", "To", "With");
$strArray = explode(" ", preg_replace("/(?<=(?<!:|’s)\W) $strArray = explode(" ", preg_replace("/(?<=(?<!:|’s)\W)
(A|An|And|At|For|In|Of|On|Or|The|To|With) (A|An|And|At|For|In|Of|On|Or|The|To|With)
(?=\W)/e", 'strtolower("$1")', ucwords(strtolower($str)))); (?=\W)/e", 'strtolower("$1")', ucwords(strtolower($str))));
foreach ($strArray as &$word) { foreach ($strArray as &$word) {
if (strlen($word) <= 4 && !in_array($word, $shortWords)) if (strlen($word) <= 4 && !in_array($word, $shortWords))
$word = strtoupper($word); $word = strtoupper($word);
} }
return implode(" ", $strArray); return implode(" ", $strArray);
} }
function percent($num_amount, $num_total) { function percent($num_amount, $num_total) {
$count1 = $num_amount / $num_total; $count1 = $num_amount / $num_total;
$count2 = $count1 * 100; $count2 = $count1 * 100;
$count = number_format($count2, 2); $count = number_format($count2, 2);
return $count; return $count;
} }
function array_sum_all($a) { function array_sum_all($a) {
if (!is_array($a)) if (!is_array($a))
return $a; return $a;
foreach ($a as $key => $value) foreach ($a as $key => $value)
$totale += array_sum_all($value); $totale += array_sum_all($value);
return $totale; return $totale;
} }
// magic query modifiers // magic query modifiers
$agency = filter_var($_REQUEST['agency'], FILTER_SANITIZE_STRING); $agency = filter_var($_REQUEST['agency'], FILTER_SANITIZE_STRING);
if ($agency != "") if ($agency != "")
$agencyQ = "agencyName = '" . $agency . "' AND "; $agencyQ = "agencyName = '" . $agency . "' AND ";
$supplier = filter_var($_REQUEST['supplier'], FILTER_SANITIZE_STRING); $supplier = filter_var($_REQUEST['supplier'], FILTER_SANITIZE_STRING);
if ($supplier != "") { if ($supplier != "") {
$supplierParts = explode("-", $supplier); $supplierParts = explode("-", $supplier);
$supplierName = "%" . $supplierParts[1] . "%"; $supplierName = "%" . $supplierParts[1] . "%";
$supplierABN = $supplierParts[0]; $supplierABN = $supplierParts[0];
if ($supplierParts[0] > 0) if ($supplierParts[0] > 0)
$supplierQ = ' "supplierABN" = :supplierABN AND '; $supplierQ = ' "supplierABN" = :supplierABN AND ';
else else
$supplierQ = ' "supplierName" LIKE :supplierName AND '; $supplierQ = ' "supplierName" LIKE :supplierName AND ';
} }
$startYear = 2007; $startYear = 2007;
$year = filter_var($_REQUEST['year'], FILTER_SANITIZE_NUMBER_INT); $year = filter_var($_REQUEST['year'], FILTER_SANITIZE_NUMBER_INT);
if ($year != "") if ($year != "")
$yearQ = "YEAR(publishDate) = " . $year . " AND "; $yearQ = "YEAR(publishDate) = " . $year . " AND ";
$standardQ = ' "childCN" is null '; // AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2010'; $standardQ = ' "childCN" is null '; // AND YEAR(contractStart) >= 2007 AND YEAR(contractStart) <= 2010';
$start = 0.0; $start = 0.0;
   
  function local_url() {
  return "http://" . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['PHP_SELF']), '/\\') . "/";
  }
function include_header($title) { function include_header($title) {
global $start; global $start;
?> ?>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd"> "http://www.w3.org/TR/html4/strict.dtd">
<html> <html>
<head> <head>
<title>Contract Dashboard - <?php echo $title; ?></title> <title>Contract Dashboard - <?php echo $title; ?></title>
<link rel="stylesheet" type="text/css" href="bootstrap.min.css"> <link rel="stylesheet" type="text/css" href="bootstrap.min.css">
<!-- Le HTML5 shim, for IE6-8 support of HTML elements --> <!-- Le HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]> <!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]--> <![endif]-->
<script type="text/javascript" src="lib/bsn.AutoSuggest_2.1.3_comp.js" charset="utf-8"></script> <script type="text/javascript" src="lib/bsn.AutoSuggest_2.1.3_comp.js" charset="utf-8"></script>
<link rel="stylesheet" href="autosuggest_inquisitor.css" type="text/css" media="screen" charset="utf-8" /> <link rel="stylesheet" href="autosuggest_inquisitor.css" type="text/css" media="screen" charset="utf-8" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function() $(document).ready(function()
{ {
//hide the all of the element with class msg_body //hide the all of the element with class msg_body
$(".msg_body").hide(); $(".msg_body").hide();
//toggle the componenet with class msg_body //toggle the componenet with class msg_body
$(".msg_head").click(function() $(".msg_head").click(function()
{ {
$(this).next(".msg_body").slideToggle(600); $(this).next(".msg_body").slideToggle(600);
}); });
}); });
</script> </script>
<style type="text/css" title="currentStyle"> <style type="text/css" title="currentStyle">
@import "media/css/demo_table.css"; @import "media/css/demo_table.css";
</style> </style>
<script type="text/javascript" language="javascript" src="media/js/jquery.dataTables.js"></script> <script type="text/javascript" language="javascript" src="media/js/jquery.dataTables.js"></script>
<script type="text/javascript" language="javascript" src="lib/bootstrap-dropdown.js"></script> <script type="text/javascript" language="javascript" src="lib/bootstrap-dropdown.js"></script>
<script type="text/javascript" charset="utf-8"> <script type="text/javascript" charset="utf-8">
jQuery.fn.dataTableExt.aTypes.unshift( jQuery.fn.dataTableExt.aTypes.unshift(
function ( sData ) function ( sData )
{ {
var sValidChars = "0123456789.-,"; var sValidChars = "0123456789.-,";
var Char; var Char;
   
/* Check the numeric part */ /* Check the numeric part */
for ( i=1 ; i<sData.length ; i++ ) for ( i=1 ; i<sData.length ; i++ )
{ {
Char = sData.charAt(i); Char = sData.charAt(i);
if (sValidChars.indexOf(Char) == -1) if (sValidChars.indexOf(Char) == -1)
{ {
return null; return null;
} }
} }
   
/* Check prefixed by currency */ /* Check prefixed by currency */
if ( sData.charAt(0) == '$' || sData.charAt(0) == '£' ) if ( sData.charAt(0) == '$' || sData.charAt(0) == '£' )
{ {
return 'currency'; return 'currency';
} }
return null; return null;
} }
); );
jQuery.fn.dataTableExt.oSort['currency-asc'] = function(a,b) { jQuery.fn.dataTableExt.oSort['currency-asc'] = function(a,b) {
/* Remove any commas (assumes that if present all strings will have a fixed number of d.p) */ /* Remove any commas (assumes that if present all strings will have a fixed number of d.p) */
var x = a == "-" ? 0 : a.replace( /,/g, "" ); var x = a == "-" ? 0 : a.replace( /,/g, "" );
var y = b == "-" ? 0 : b.replace( /,/g, "" ); var y = b == "-" ? 0 : b.replace( /,/g, "" );
   
/* Remove the currency sign */ /* Remove the currency sign */
x = x.substring( 1 ); x = x.substring( 1 );
y = y.substring( 1 ); y = y.substring( 1 );
   
/* Parse and return */ /* Parse and return */
x = parseFloat( x ); x = parseFloat( x );
y = parseFloat( y ); y = parseFloat( y );
return x - y; return x - y;
}; };
jQuery.fn.dataTableExt.oSort['currency-desc'] = function(a,b) { jQuery.fn.dataTableExt.oSort['currency-desc'] = function(a,b) {
/* Remove any commas (assumes that if present all strings will have a fixed number of d.p) */ /* Remove any commas (assumes that if present all strings will have a fixed number of d.p) */
var x = a == "-" ? 0 : a.replace( /,/g, "" ); var x = a == "-" ? 0 : a.replace( /,/g, "" );
var y = b == "-" ? 0 : b.replace( /,/g, "" ); var y = b == "-" ? 0 : b.replace( /,/g, "" );
   
/* Remove the currency sign */ /* Remove the currency sign */
x = x.substring( 1 ); x = x.substring( 1 );
y = y.substring( 1 ); y = y.substring( 1 );
   
/* Parse and return */ /* Parse and return */
x = parseFloat( x ); x = parseFloat( x );
y = parseFloat( y ); y = parseFloat( y );
return y - x; return y - x;
}; };
$(document).ready(function() { $(document).ready(function() {
$('table').dataTable(); $('table').dataTable();
} ); } );
</script> </script>
<link type="text/css" rel="stylesheet" href="style.css"> <link type="text/css" rel="stylesheet" href="style.css">
</head> </head>
<body> <body>
<div class="topbar"> <div class="topbar">
<div class="topbar-inner"> <div class="topbar-inner">
<div class="container-fluid"> <div class="container-fluid">
<a class="brand" href="#">contract dashboard</a> <a class="brand" href="#">contract dashboard</a>
<ul class="nav"> <ul class="nav">
<li><a href="displayAgency.php">agencies</a></li> <li><a href="displayAgency.php">agencies</a></li>
<li><a href="displaySupplier.php">suppliers</a></li> <li><a href="displaySupplier.php">suppliers</a></li>
<li><a href="displayCategory.php">categories</a></li> <li><a href="displayCategory.php">categories</a></li>
<li><a href="displayCalendar.php">time periods</a></li> <li><a href="displayCalendar.php">time periods</a></li>
<!-- <li class="dropdown"> <!-- <li class="dropdown">
<a href="#" class="dropdown-toggle">metrics</a> <a href="#" class="dropdown-toggle">metrics</a>
<ul class="dropdown-menu">--> <ul class="dropdown-menu">-->
<li><a href="displayProcurementMethod.php">tenderm</a></li> <li><a href="displayProcurementMethod.php">tenderm</a></li>
<li><a href="displayConfidentialities.php">confidentiality</a></li> <li><a href="displayConfidentialities.php">confidentiality</a></li>
<li><a href="displayConsultancies.php">consultancies</a></li> <li><a href="displayConsultancies.php">consultancies</a></li>
<li><a href="displayAmendments.php">amendments</a></li> <li><a href="displayAmendments.php">amendments</a></li>
<li><a href="displayMap.php">geo</a></li> <li><a href="displayMap.php">geo</a></li>
<!-- </ul> <!-- </ul>
</li>--> </li>-->
</ul> </ul>
   
   
<form method="post" action="search.php" class="pull-right"> <form method="post" action="search.php" class="pull-right">
<input type="text" id="searchKeyword" name="searchKeyword" value="" placeholder="Search" /> <input type="text" id="searchKeyword" name="searchKeyword" value="" placeholder="Search" />
<input type="hidden" id="searchID" name="searchID" value=""/> <input type="hidden" id="searchID" name="searchID" value=""/>
</form> </form>
   
</div> </div>
</div><!-- /topbar-inner --> </div><!-- /topbar-inner -->
</div><!-- /topbar --> </div><!-- /topbar -->
</div><!-- /topbar-wrapper --> </div><!-- /topbar-wrapper -->
<script type="text/javascript"> <script type="text/javascript">
   
var options_xml = { var options_xml = {
script: function (input) { return "search_autosuggest.php?input="+input; }, script: function (input) { return "search_autosuggest.php?input="+input; },
varname:"input", varname:"input",
callback: function (obj) { document.getElementById('searchID').value = obj.id; } callback: function (obj) { document.getElementById('searchID').value = obj.id; }
}; };
var as_xml = new bsn.AutoSuggest('searchKeyword', options_xml); var as_xml = new bsn.AutoSuggest('searchKeyword', options_xml);
</script> </script>
<div class="container-fluid"> <div class="container-fluid">
<div class="sidebar"> <div class="sidebar">
<div class="well"> <div class="well">
Filter by:<li> Filter by:<li>
<li>year <li>year
<li><li>2008</li> <li><li>2008</li>
</li> </li>
</li> </li>
</li> <br> </li> <br>
</div> </div> </div> </div>
<div class="content"> <div class="content">
<?php <?php
$start = (float) array_sum(explode(' ', microtime())); $start = (float) array_sum(explode(' ', microtime()));
} }
   
function include_footer() { function include_footer() {
global $start; global $start;
$end = (float) array_sum(explode(' ', microtime())); $end = (float) array_sum(explode(' ', microtime()));
   
echo ' <footer>' . "Processing time: " . sprintf("%.4f", ($end - $start)) . " seconds" . ' <footer>'; echo ' <footer>' . "Processing time: " . sprintf("%.4f", ($end - $start)) . " seconds" . ' <footer>';
echo '</div> </div></body> </html>';  
} if (strpos($_SERVER['SERVER_NAME'], ".gs")) {
  ?>
include ("graphs.inc.php"); <script type="text/javascript">
?>  
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-12341040-3']);
  _gaq.push(['_trackPageview']);
   
  (function() {
  var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
  ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
  var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
   
  </script>
  <?php
  }
  echo '</div> </div></body> </html>';
  }
   
  include ("graphs.inc.php");
   
   
   
   
  <?php
 
  /**
  * This module documents the main interface with the OpenID consumer
  * library. The only part of the library which has to be used and
  * isn't documented in full here is the store required to create an
  * Auth_OpenID_Consumer instance. More on the abstract store type and
  * concrete implementations of it that are provided in the
  * documentation for the Auth_OpenID_Consumer constructor.
  *
  * OVERVIEW
  *
  * The OpenID identity verification process most commonly uses the
  * following steps, as visible to the user of this library:
  *
  * 1. The user enters their OpenID into a field on the consumer's
  * site, and hits a login button.
  * 2. The consumer site discovers the user's OpenID server using the
  * YADIS protocol.
  * 3. The consumer site sends the browser a redirect to the identity
  * server. This is the authentication request as described in
  * the OpenID specification.
  * 4. The identity server's site sends the browser a redirect back
  * to the consumer site. This redirect contains the server's
  * response to the authentication request.
  *
  * The most important part of the flow to note is the consumer's site
  * must handle two separate HTTP requests in order to perform the full
  * identity check.
  *
  * LIBRARY DESIGN
  *
  * This consumer library is designed with that flow in mind. The goal
  * is to make it as easy as possible to perform the above steps
  * securely.
  *
  * At a high level, there are two important parts in the consumer
  * library. The first important part is this module, which contains
  * the interface to actually use this library. The second is the
  * Auth_OpenID_Interface class, which describes the interface to use
  * if you need to create a custom method for storing the state this
  * library needs to maintain between requests.
  *
  * In general, the second part is less important for users of the
  * library to know about, as several implementations are provided
  * which cover a wide variety of situations in which consumers may use
  * the library.
  *
  * This module contains a class, Auth_OpenID_Consumer, with methods
  * corresponding to the actions necessary in each of steps 2, 3, and 4
  * described in the overview. Use of this library should be as easy
  * as creating an Auth_OpenID_Consumer instance and calling the
  * methods appropriate for the action the site wants to take.
  *
  * STORES AND DUMB MODE
  *
  * OpenID is a protocol that works best when the consumer site is able
  * to store some state. This is the normal mode of operation for the
  * protocol, and is sometimes referred to as smart mode. There is
  * also a fallback mode, known as dumb mode, which is available when
  * the consumer site is not able to store state. This mode should be
  * avoided when possible, as it leaves the implementation more
  * vulnerable to replay attacks.
  *
  * The mode the library works in for normal operation is determined by
  * the store that it is given. The store is an abstraction that
  * handles the data that the consumer needs to manage between http
  * requests in order to operate efficiently and securely.
  *
  * Several store implementation are provided, and the interface is
  * fully documented so that custom stores can be used as well. See
  * the documentation for the Auth_OpenID_Consumer class for more
  * information on the interface for stores. The implementations that
  * are provided allow the consumer site to store the necessary data in
  * several different ways, including several SQL databases and normal
  * files on disk.
  *
  * There is an additional concrete store provided that puts the system
  * in dumb mode. This is not recommended, as it removes the library's
  * ability to stop replay attacks reliably. It still uses time-based
  * checking to make replay attacks only possible within a small
  * window, but they remain possible within that window. This store
  * should only be used if the consumer site has no way to retain data
  * between requests at all.
  *
  * IMMEDIATE MODE
  *
  * In the flow described above, the user may need to confirm to the
  * lidentity server that it's ok to authorize his or her identity.
  * The server may draw pages asking for information from the user
  * before it redirects the browser back to the consumer's site. This
  * is generally transparent to the consumer site, so it is typically
  * ignored as an implementation detail.
  *
  * There can be times, however, where the consumer site wants to get a
  * response immediately. When this is the case, the consumer can put
  * the library in immediate mode. In immediate mode, there is an
  * extra response possible from the server, which is essentially the
  * server reporting that it doesn't have enough information to answer
  * the question yet.
  *
  * USING THIS LIBRARY
  *
  * Integrating this library into an application is usually a
  * relatively straightforward process. The process should basically
  * follow this plan:
  *
  * Add an OpenID login field somewhere on your site. When an OpenID
  * is entered in that field and the form is submitted, it should make
  * a request to the your site which includes that OpenID URL.
  *
  * First, the application should instantiate the Auth_OpenID_Consumer
  * class using the store of choice (Auth_OpenID_FileStore or one of
  * the SQL-based stores). If the application has a custom
  * session-management implementation, an object implementing the
  * {@link Auth_Yadis_PHPSession} interface should be passed as the
  * second parameter. Otherwise, the default uses $_SESSION.
  *
  * Next, the application should call the Auth_OpenID_Consumer object's
  * 'begin' method. This method takes the OpenID URL. The 'begin'
  * method returns an Auth_OpenID_AuthRequest object.
  *
  * Next, the application should call the 'redirectURL' method of the
  * Auth_OpenID_AuthRequest object. The 'return_to' URL parameter is
  * the URL that the OpenID server will send the user back to after
  * attempting to verify his or her identity. The 'trust_root' is the
  * URL (or URL pattern) that identifies your web site to the user when
  * he or she is authorizing it. Send a redirect to the resulting URL
  * to the user's browser.
  *
  * That's the first half of the authentication process. The second
  * half of the process is done after the user's ID server sends the
  * user's browser a redirect back to your site to complete their
  * login.
  *
  * When that happens, the user will contact your site at the URL given
  * as the 'return_to' URL to the Auth_OpenID_AuthRequest::redirectURL
  * call made above. The request will have several query parameters
  * added to the URL by the identity server as the information
  * necessary to finish the request.
  *
  * Lastly, instantiate an Auth_OpenID_Consumer instance as above and
  * call its 'complete' method, passing in all the received query
  * arguments.
  *
  * There are multiple possible return types possible from that
  * method. These indicate the whether or not the login was successful,
  * and include any additional information appropriate for their type.
  *
  * PHP versions 4 and 5
  *
  * LICENSE: See the COPYING file included in this distribution.
  *
  * @package OpenID
  * @author JanRain, Inc. <openid@janrain.com>
  * @copyright 2005-2008 Janrain, Inc.
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  */
 
  /**
  * Require utility classes and functions for the consumer.
  */
  require_once "Auth/OpenID.php";
  require_once "Auth/OpenID/Message.php";
  require_once "Auth/OpenID/HMAC.php";
  require_once "Auth/OpenID/Association.php";
  require_once "Auth/OpenID/CryptUtil.php";
  require_once "Auth/OpenID/DiffieHellman.php";
  require_once "Auth/OpenID/KVForm.php";
  require_once "Auth/OpenID/Nonce.php";
  require_once "Auth/OpenID/Discover.php";
  require_once "Auth/OpenID/URINorm.php";
  require_once "Auth/Yadis/Manager.php";
  require_once "Auth/Yadis/XRI.php";
 
  /**
  * This is the status code returned when the complete method returns
  * successfully.
  */
  define('Auth_OpenID_SUCCESS', 'success');
 
  /**
  * Status to indicate cancellation of OpenID authentication.
  */
  define('Auth_OpenID_CANCEL', 'cancel');
 
  /**
  * This is the status code completeAuth returns when the value it
  * received indicated an invalid login.
  */
  define('Auth_OpenID_FAILURE', 'failure');
 
  /**
  * This is the status code completeAuth returns when the
  * {@link Auth_OpenID_Consumer} instance is in immediate mode, and the
  * identity server sends back a URL to send the user to to complete his
  * or her login.
  */
  define('Auth_OpenID_SETUP_NEEDED', 'setup needed');
 
  /**
  * This is the status code beginAuth returns when the page fetched
  * from the entered OpenID URL doesn't contain the necessary link tags
  * to function as an identity page.
  */
  define('Auth_OpenID_PARSE_ERROR', 'parse error');
 
  /**
  * An OpenID consumer implementation that performs discovery and does
  * session management. See the Consumer.php file documentation for
  * more information.
  *
  * @package OpenID
  */
  class Auth_OpenID_Consumer {
 
  /**
  * @access private
  */
  var $discoverMethod = 'Auth_OpenID_discover';
 
  /**
  * @access private
  */
  var $session_key_prefix = "_openid_consumer_";
 
  /**
  * @access private
  */
  var $_token_suffix = "last_token";
 
  /**
  * Initialize a Consumer instance.
  *
  * You should create a new instance of the Consumer object with
  * every HTTP request that handles OpenID transactions.
  *
  * @param Auth_OpenID_OpenIDStore $store This must be an object
  * that implements the interface in {@link
  * Auth_OpenID_OpenIDStore}. Several concrete implementations are
  * provided, to cover most common use cases. For stores backed by
  * MySQL, PostgreSQL, or SQLite, see the {@link
  * Auth_OpenID_SQLStore} class and its sublcasses. For a
  * filesystem-backed store, see the {@link Auth_OpenID_FileStore}
  * module. As a last resort, if it isn't possible for the server
  * to store state at all, an instance of {@link
  * Auth_OpenID_DumbStore} can be used.
  *
  * @param mixed $session An object which implements the interface
  * of the {@link Auth_Yadis_PHPSession} class. Particularly, this
  * object is expected to have these methods: get($key), set($key),
  * $value), and del($key). This defaults to a session object
  * which wraps PHP's native session machinery. You should only
  * need to pass something here if you have your own sessioning
  * implementation.
  *
  * @param str $consumer_cls The name of the class to instantiate
  * when creating the internal consumer object. This is used for
  * testing.
  */
  function Auth_OpenID_Consumer($store, $session = null,
  $consumer_cls = null)
  {
  if ($session === null) {
  $session = new Auth_Yadis_PHPSession();
  }
 
  $this->session = $session;
 
  if ($consumer_cls !== null) {
  $this->consumer = new $consumer_cls($store);
  } else {
  $this->consumer = new Auth_OpenID_GenericConsumer($store);
  }
 
  $this->_token_key = $this->session_key_prefix . $this->_token_suffix;
  }
 
  /**
  * Used in testing to define the discovery mechanism.
  *
  * @access private
  */
  function getDiscoveryObject($session, $openid_url,
  $session_key_prefix)
  {
  return new Auth_Yadis_Discovery($session, $openid_url,
  $session_key_prefix);
  }
 
  /**
  * Start the OpenID authentication process. See steps 1-2 in the
  * overview at the top of this file.
  *
  * @param string $user_url Identity URL given by the user. This
  * method performs a textual transformation of the URL to try and
  * make sure it is normalized. For example, a user_url of
  * example.com will be normalized to http://example.com/
  * normalizing and resolving any redirects the server might issue.
  *
  * @param bool $anonymous True if the OpenID request is to be sent
  * to the server without any identifier information. Use this
  * when you want to transport data but don't want to do OpenID
  * authentication with identifiers.
  *
  * @return Auth_OpenID_AuthRequest $auth_request An object
  * containing the discovered information will be returned, with a
  * method for building a redirect URL to the server, as described
  * in step 3 of the overview. This object may also be used to add
  * extension arguments to the request, using its 'addExtensionArg'
  * method.
  */
  function begin($user_url, $anonymous=false)
  {
  $openid_url = $user_url;
 
  $disco = $this->getDiscoveryObject($this->session,
  $openid_url,
  $this->session_key_prefix);
 
  // Set the 'stale' attribute of the manager. If discovery
  // fails in a fatal way, the stale flag will cause the manager
  // to be cleaned up next time discovery is attempted.
 
  $m = $disco->getManager();
  $loader = new Auth_Yadis_ManagerLoader();
 
  if ($m) {
  if ($m->stale) {
  $disco->destroyManager();
  } else {
  $m->stale = true;
  $disco->session->set($disco->session_key,
  serialize($loader->toSession($m)));
  }
  }
 
  $endpoint = $disco->getNextService($this->discoverMethod,
  $this->consumer->fetcher);
 
  // Reset the 'stale' attribute of the manager.
  $m = $disco->getManager();
  if ($m) {
  $m->stale = false;
  $disco->session->set($disco->session_key,
  serialize($loader->toSession($m)));
  }
 
  if ($endpoint === null) {
  return null;
  } else {
  return $this->beginWithoutDiscovery($endpoint,
  $anonymous);
  }
  }
 
  /**
  * Start OpenID verification without doing OpenID server
  * discovery. This method is used internally by Consumer.begin
  * after discovery is performed, and exists to provide an
  * interface for library users needing to perform their own
  * discovery.
  *
  * @param Auth_OpenID_ServiceEndpoint $endpoint an OpenID service
  * endpoint descriptor.
  *
  * @param bool anonymous Set to true if you want to perform OpenID
  * without identifiers.
  *
  * @return Auth_OpenID_AuthRequest $auth_request An OpenID
  * authentication request object.
  */
  function beginWithoutDiscovery($endpoint, $anonymous=false)
  {
  $loader = new Auth_OpenID_ServiceEndpointLoader();
  $auth_req = $this->consumer->begin($endpoint);
  $this->session->set($this->_token_key,
  $loader->toSession($auth_req->endpoint));
  if (!$auth_req->setAnonymous($anonymous)) {
  return new Auth_OpenID_FailureResponse(null,
  "OpenID 1 requests MUST include the identifier " .
  "in the request.");
  }
  return $auth_req;
  }
 
  /**
  * Called to interpret the server's response to an OpenID
  * request. It is called in step 4 of the flow described in the
  * consumer overview.
  *
  * @param string $current_url The URL used to invoke the application.
  * Extract the URL from your application's web
  * request framework and specify it here to have it checked
  * against the openid.current_url value in the response. If
  * the current_url URL check fails, the status of the
  * completion will be FAILURE.
  *
  * @param array $query An array of the query parameters (key =>
  * value pairs) for this HTTP request. Defaults to null. If
  * null, the GET or POST data are automatically gotten from the
  * PHP environment. It is only useful to override $query for
  * testing.
  *
  * @return Auth_OpenID_ConsumerResponse $response A instance of an
  * Auth_OpenID_ConsumerResponse subclass. The type of response is
  * indicated by the status attribute, which will be one of
  * SUCCESS, CANCEL, FAILURE, or SETUP_NEEDED.
  */
  function complete($current_url, $query=null)
  {
  if ($current_url && !is_string($current_url)) {
  // This is ugly, but we need to complain loudly when
  // someone uses the API incorrectly.
  trigger_error("current_url must be a string; see NEWS file " .
  "for upgrading notes.",
  E_USER_ERROR);
  }
 
  if ($query === null) {
  $query = Auth_OpenID::getQuery();
  }
 
  $loader = new Auth_OpenID_ServiceEndpointLoader();
  $endpoint_data = $this->session->get($this->_token_key);
  $endpoint =
  $loader->fromSession($endpoint_data);
 
  $message = Auth_OpenID_Message::fromPostArgs($query);
  $response = $this->consumer->complete($message, $endpoint,
  $current_url);
  $this->session->del($this->_token_key);
 
  if (in_array($response->status, array(Auth_OpenID_SUCCESS,
  Auth_OpenID_CANCEL))) {
  if ($response->identity_url !== null) {
  $disco = $this->getDiscoveryObject($this->session,
  $response->identity_url,
  $this->session_key_prefix);
  $disco->cleanup(true);
  }
  }
 
  return $response;
  }
  }
 
  /**
  * A class implementing HMAC/DH-SHA1 consumer sessions.
  *
  * @package OpenID
  */
  class Auth_OpenID_DiffieHellmanSHA1ConsumerSession {
  var $session_type = 'DH-SHA1';
  var $hash_func = 'Auth_OpenID_SHA1';
  var $secret_size = 20;
  var $allowed_assoc_types = array('HMAC-SHA1');
 
  function Auth_OpenID_DiffieHellmanSHA1ConsumerSession($dh = null)
  {
  if ($dh === null) {
  $dh = new Auth_OpenID_DiffieHellman();
  }
 
  $this->dh = $dh;
  }
 
  function getRequest()
  {
  $math = Auth_OpenID_getMathLib();
 
  $cpub = $math->longToBase64($this->dh->public);
 
  $args = array('dh_consumer_public' => $cpub);
 
  if (!$this->dh->usingDefaultValues()) {
  $args = array_merge($args, array(
  'dh_modulus' =>
  $math->longToBase64($this->dh->mod),
  'dh_gen' =>
  $math->longToBase64($this->dh->gen)));
  }
 
  return $args;
  }
 
  function extractSecret($response)
  {
  if (!$response->hasKey(Auth_OpenID_OPENID_NS,
  'dh_server_public')) {
  return null;
  }
 
  if (!$response->hasKey(Auth_OpenID_OPENID_NS,
  'enc_mac_key')) {
  return null;
  }
 
  $math = Auth_OpenID_getMathLib();
 
  $spub = $math->base64ToLong($response->getArg(Auth_OpenID_OPENID_NS,
  'dh_server_public'));
  $enc_mac_key = base64_decode($response->getArg(Auth_OpenID_OPENID_NS,
  'enc_mac_key'));
 
  return $this->dh->xorSecret($spub, $enc_mac_key, $this->hash_func);
  }
  }
 
  /**
  * A class implementing HMAC/DH-SHA256 consumer sessions.
  *
  * @package OpenID
  */
  class Auth_OpenID_DiffieHellmanSHA256ConsumerSession extends
  Auth_OpenID_DiffieHellmanSHA1ConsumerSession {
  var $session_type = 'DH-SHA256';
  var $hash_func = 'Auth_OpenID_SHA256';
  var $secret_size = 32;
  var $allowed_assoc_types = array('HMAC-SHA256');
  }
 
  /**
  * A class implementing plaintext consumer sessions.
  *
  * @package OpenID
  */
  class Auth_OpenID_PlainTextConsumerSession {
  var $session_type = 'no-encryption';
  var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256');
 
  function getRequest()
  {
  return array();
  }
 
  function extractSecret($response)
  {
  if (!$response->hasKey(Auth_OpenID_OPENID_NS, 'mac_key')) {
  return null;
  }
 
  return base64_decode($response->getArg(Auth_OpenID_OPENID_NS,
  'mac_key'));
  }
  }
 
  /**
  * Returns available session types.
  */
  function Auth_OpenID_getAvailableSessionTypes()
  {
  $types = array(
  'no-encryption' => 'Auth_OpenID_PlainTextConsumerSession',
  'DH-SHA1' => 'Auth_OpenID_DiffieHellmanSHA1ConsumerSession',
  'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ConsumerSession');
 
  return $types;
  }
 
  /**
  * This class is the interface to the OpenID consumer logic.
  * Instances of it maintain no per-request state, so they can be
  * reused (or even used by multiple threads concurrently) as needed.
  *
  * @package OpenID
  */
  class Auth_OpenID_GenericConsumer {
  /**
  * @access private
  */
  var $discoverMethod = 'Auth_OpenID_discover';
 
  /**
  * This consumer's store object.
  */
  var $store;
 
  /**
  * @access private
  */
  var $_use_assocs;
 
  /**
  * @access private
  */
  var $openid1_nonce_query_arg_name = 'janrain_nonce';
 
  /**
  * Another query parameter that gets added to the return_to for
  * OpenID 1; if the user's session state is lost, use this claimed
  * identifier to do discovery when verifying the response.
  */
  var $openid1_return_to_identifier_name = 'openid1_claimed_id';
 
  /**
  * This method initializes a new {@link Auth_OpenID_Consumer}
  * instance to access the library.
  *
  * @param Auth_OpenID_OpenIDStore $store This must be an object
  * that implements the interface in {@link Auth_OpenID_OpenIDStore}.
  * Several concrete implementations are provided, to cover most common use
  * cases. For stores backed by MySQL, PostgreSQL, or SQLite, see
  * the {@link Auth_OpenID_SQLStore} class and its sublcasses. For a
  * filesystem-backed store, see the {@link Auth_OpenID_FileStore} module.
  * As a last resort, if it isn't possible for the server to store
  * state at all, an instance of {@link Auth_OpenID_DumbStore} can be used.
  *
  * @param bool $immediate This is an optional boolean value. It
  * controls whether the library uses immediate mode, as explained
  * in the module description. The default value is False, which
  * disables immediate mode.
  */
  function Auth_OpenID_GenericConsumer($store)
  {
  $this->store = $store;
  $this->negotiator = Auth_OpenID_getDefaultNegotiator();
  $this->_use_assocs = (is_null($this->store) ? false : true);
 
  $this->fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
 
  $this->session_types = Auth_OpenID_getAvailableSessionTypes();
  }
 
  /**
  * Called to begin OpenID authentication using the specified
  * {@link Auth_OpenID_ServiceEndpoint}.
  *
  * @access private
  */
  function begin($service_endpoint)
  {
  $assoc = $this->_getAssociation($service_endpoint);
  $r = new Auth_OpenID_AuthRequest($service_endpoint, $assoc);
  $r->return_to_args[$this->openid1_nonce_query_arg_name] =
  Auth_OpenID_mkNonce();
 
  if ($r->message->isOpenID1()) {
  $r->return_to_args[$this->openid1_return_to_identifier_name] =
  $r->endpoint->claimed_id;
  }
 
  return $r;
  }
 
  /**
  * Given an {@link Auth_OpenID_Message}, {@link
  * Auth_OpenID_ServiceEndpoint} and optional return_to URL,
  * complete OpenID authentication.
  *
  * @access private
  */
  function complete($message, $endpoint, $return_to)
  {
  $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode',
  '<no mode set>');
 
  $mode_methods = array(
  'cancel' => '_complete_cancel',
  'error' => '_complete_error',
  'setup_needed' => '_complete_setup_needed',
  'id_res' => '_complete_id_res',
  );
 
  $method = Auth_OpenID::arrayGet($mode_methods, $mode,
  '_completeInvalid');
 
  return call_user_func_array(array($this, $method),
  array($message, &$endpoint, $return_to));
  }
 
  /**
  * @access private
  */
  function _completeInvalid($message, $endpoint, $unused)
  {
  $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode',
  '<No mode set>');
 
  return new Auth_OpenID_FailureResponse($endpoint,
  sprintf("Invalid openid.mode '%s'", $mode));
  }
 
  /**
  * @access private
  */
  function _complete_cancel($message, $endpoint, $unused)
  {
  return new Auth_OpenID_CancelResponse($endpoint);
  }
 
  /**
  * @access private
  */
  function _complete_error($message, $endpoint, $unused)
  {
  $error = $message->getArg(Auth_OpenID_OPENID_NS, 'error');
  $contact = $message->getArg(Auth_OpenID_OPENID_NS, 'contact');
  $reference = $message->getArg(Auth_OpenID_OPENID_NS, 'reference');
 
  return new Auth_OpenID_FailureResponse($endpoint, $error,
  $contact, $reference);
  }
 
  /**
  * @access private
  */
  function _complete_setup_needed($message, $endpoint, $unused)
  {
  if (!$message->isOpenID2()) {
  return $this->_completeInvalid($message, $endpoint);
  }
 
  $user_setup_url = $message->getArg(Auth_OpenID_OPENID2_NS,
  'user_setup_url');
  return new Auth_OpenID_SetupNeededResponse($endpoint, $user_setup_url);
  }
 
  /**
  * @access private
  */
  function _complete_id_res($message, $endpoint, $return_to)
  {
  $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS,
  'user_setup_url');
 
  if ($this->_checkSetupNeeded($message)) {
  return new Auth_OpenID_SetupNeededResponse(
  $endpoint, $user_setup_url);
  } else {
  return $this->_doIdRes($message, $endpoint, $return_to);
  }
  }
 
  /**
  * @access private
  */
  function _checkSetupNeeded($message)
  {
  // In OpenID 1, we check to see if this is a cancel from
  // immediate mode by the presence of the user_setup_url
  // parameter.
  if ($message->isOpenID1()) {
  $user_setup_url = $message->getArg(Auth_OpenID_OPENID1_NS,
  'user_setup_url');
  if ($user_setup_url !== null) {
  return true;
  }
  }
 
  return false;
  }
 
  /**
  * @access private
  */
  function _doIdRes($message, $endpoint, $return_to)
  {
  // Checks for presence of appropriate fields (and checks
  // signed list fields)
  $result = $this->_idResCheckForFields($message);
 
  if (Auth_OpenID::isFailure($result)) {
  return $result;
  }
 
  if (!$this->_checkReturnTo($message, $return_to)) {
  return new Auth_OpenID_FailureResponse(null,
  sprintf("return_to does not match return URL. Expected %s, got %s",
  $return_to,
  $message->getArg(Auth_OpenID_OPENID_NS, 'return_to')));
  }
 
  // Verify discovery information:
  $result = $this->_verifyDiscoveryResults($message, $endpoint);
 
  if (Auth_OpenID::isFailure($result)) {
  return $result;
  }
 
  $endpoint = $result;
 
  $result = $this->_idResCheckSignature($message,
  $endpoint->server_url);
 
  if (Auth_OpenID::isFailure($result)) {
  return $result;
  }
 
  $result = $this->_idResCheckNonce($message, $endpoint);
 
  if (Auth_OpenID::isFailure($result)) {
  return $result;
  }
 
  $signed_list_str = $message->getArg(Auth_OpenID_OPENID_NS, 'signed',
  Auth_OpenID_NO_DEFAULT);
  if (Auth_OpenID::isFailure($signed_list_str)) {
  return $signed_list_str;
  }
  $signed_list = explode(',', $signed_list_str);
 
  $signed_fields = Auth_OpenID::addPrefix($signed_list, "openid.");
 
  return new Auth_OpenID_SuccessResponse($endpoint, $message,
  $signed_fields);
 
  }
 
  /**
  * @access private
  */
  function _checkReturnTo($message, $return_to)
  {
  // Check an OpenID message and its openid.return_to value
  // against a return_to URL from an application. Return True
  // on success, False on failure.
 
  // Check the openid.return_to args against args in the
  // original message.
  $result = Auth_OpenID_GenericConsumer::_verifyReturnToArgs(
  $message->toPostArgs());
  if (Auth_OpenID::isFailure($result)) {
  return false;
  }
 
  // Check the return_to base URL against the one in the
  // message.
  $msg_return_to = $message->getArg(Auth_OpenID_OPENID_NS,
  'return_to');
  if (Auth_OpenID::isFailure($return_to)) {
  // XXX log me
  return false;
  }
 
  $return_to_parts = parse_url(Auth_OpenID_urinorm($return_to));
  $msg_return_to_parts = parse_url(Auth_OpenID_urinorm($msg_return_to));
 
  // If port is absent from both, add it so it's equal in the
  // check below.
  if ((!array_key_exists('port', $return_to_parts)) &&
  (!array_key_exists('port', $msg_return_to_parts))) {
  $return_to_parts['port'] = null;
  $msg_return_to_parts['port'] = null;
  }
 
  // If path is absent from both, add it so it's equal in the
  // check below.
  if ((!array_key_exists('path', $return_to_parts)) &&
  (!array_key_exists('path', $msg_return_to_parts))) {
  $return_to_parts['path'] = null;
  $msg_return_to_parts['path'] = null;
  }
 
  // The URL scheme, authority, and path MUST be the same
  // between the two URLs.
  foreach (array('scheme', 'host', 'port', 'path') as $component) {
  // If the url component is absent in either URL, fail.
  // There should always be a scheme, host, port, and path.
  if (!array_key_exists($component, $return_to_parts)) {
  return false;
  }
 
  if (!array_key_exists($component, $msg_return_to_parts)) {
  return false;
  }
 
  if (Auth_OpenID::arrayGet($return_to_parts, $component) !==
  Auth_OpenID::arrayGet($msg_return_to_parts, $component)) {
  return false;
  }
  }
 
  return true;
  }
 
  /**
  * @access private
  */
  function _verifyReturnToArgs($query)
  {
  // Verify that the arguments in the return_to URL are present in this
  // response.
 
  $message = Auth_OpenID_Message::fromPostArgs($query);
  $return_to = $message->getArg(Auth_OpenID_OPENID_NS, 'return_to');
 
  if (Auth_OpenID::isFailure($return_to)) {
  return $return_to;
  }
  // XXX: this should be checked by _idResCheckForFields
  if (!$return_to) {
  return new Auth_OpenID_FailureResponse(null,
  "Response has no return_to");
  }
 
  $parsed_url = parse_url($return_to);
 
  $q = array();
  if (array_key_exists('query', $parsed_url)) {
  $rt_query = $parsed_url['query'];
  $q = Auth_OpenID::parse_str($rt_query);
  }
 
  foreach ($q as $rt_key => $rt_value) {
  if (!array_key_exists($rt_key, $query)) {
  return new Auth_OpenID_FailureResponse(null,
  sprintf("return_to parameter %s absent from query", $rt_key));
  } else {
  $value = $query[$rt_key];
  if ($rt_value != $value) {
  return new Auth_OpenID_FailureResponse(null,
  sprintf("parameter %s value %s does not match " .
  "return_to value %s", $rt_key,
  $value, $rt_value));
  }
  }
  }
 
  // Make sure all non-OpenID arguments in the response are also
  // in the signed return_to.
  $bare_args = $message->getArgs(Auth_OpenID_BARE_NS);
  foreach ($bare_args as $key => $value) {
  if (Auth_OpenID::arrayGet($q, $key) != $value) {
  return new Auth_OpenID_FailureResponse(null,
  sprintf("Parameter %s = %s not in return_to URL",
  $key, $value));
  }
  }
 
  return true;
  }
 
  /**
  * @access private
  */
  function _idResCheckSignature($message, $server_url)
  {
  $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS,
  'assoc_handle');
  if (Auth_OpenID::isFailure($assoc_handle)) {
  return $assoc_handle;
  }
 
  $assoc = $this->store->getAssociation($server_url, $assoc_handle);
 
  if ($assoc) {
  if ($assoc->getExpiresIn() <= 0) {
  // XXX: It might be a good idea sometimes to re-start
  // the authentication with a new association. Doing it
  // automatically opens the possibility for
  // denial-of-service by a server that just returns
  // expired associations (or really short-lived
  // associations)
  return new Auth_OpenID_FailureResponse(null,
  'Association with ' . $server_url . ' expired');
  }
 
  if (!$assoc->checkMessageSignature($message)) {
  // If we get a "bad signature" here, it means that the association
  // is unrecoverabley corrupted in some way. Any futher attempts
  // to login with this association is likely to fail. Drop it.
  $this->store->removeAssociation($server_url, $assoc_handle);
  return new Auth_OpenID_FailureResponse(null,
  "Bad signature");
  }
  } else {
  // It's not an association we know about. Stateless mode
  // is our only possible path for recovery. XXX - async
  // framework will not want to block on this call to
  // _checkAuth.
  if (!$this->_checkAuth($message, $server_url)) {
  return new Auth_OpenID_FailureResponse(null,
  "Server denied check_authentication");
  }
  }
 
  return null;
  }
 
  /**
  * @access private
  */
  function _verifyDiscoveryResults($message, $endpoint=null)
  {
  if ($message->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS) {
  return $this->_verifyDiscoveryResultsOpenID2($message,
  $endpoint);
  } else {
  return $this->_verifyDiscoveryResultsOpenID1($message,
  $endpoint);
  }
  }
 
  /**
  * @access private
  */
  function _verifyDiscoveryResultsOpenID1($message, $endpoint)
  {
  $claimed_id = $message->getArg(Auth_OpenID_BARE_NS,
  $this->openid1_return_to_identifier_name);
 
  if (($endpoint === null) && ($claimed_id === null)) {
  return new Auth_OpenID_FailureResponse($endpoint,
  'When using OpenID 1, the claimed ID must be supplied, ' .
  'either by passing it through as a return_to parameter ' .
  'or by using a session, and supplied to the GenericConsumer ' .
  'as the argument to complete()');
  } else if (($endpoint !== null) && ($claimed_id === null)) {
  $claimed_id = $endpoint->claimed_id;
  }
 
  $to_match = new Auth_OpenID_ServiceEndpoint();
  $to_match->type_uris = array(Auth_OpenID_TYPE_1_1);
  $to_match->local_id = $message->getArg(Auth_OpenID_OPENID1_NS,
  'identity');
 
  // Restore delegate information from the initiation phase
  $to_match->claimed_id = $claimed_id;
 
  if ($to_match->local_id === null) {
  return new Auth_OpenID_FailureResponse($endpoint,
  "Missing required field openid.identity");
  }
 
  $to_match_1_0 = $to_match->copy();
  $to_match_1_0->type_uris = array(Auth_OpenID_TYPE_1_0);
 
  if ($endpoint !== null) {
  $result = $this->_verifyDiscoverySingle($endpoint, $to_match);
 
  if (is_a($result, 'Auth_OpenID_TypeURIMismatch')) {
  $result = $this->_verifyDiscoverySingle($endpoint,
  $to_match_1_0);
  }
 
  if (Auth_OpenID::isFailure($result)) {
  // oidutil.log("Error attempting to use stored
  // discovery information: " + str(e))
  // oidutil.log("Attempting discovery to
  // verify endpoint")
  } else {
  return $endpoint;
  }
  }
 
  // Endpoint is either bad (failed verification) or None
  return $this->_discoverAndVerify($to_match->claimed_id,
  array($to_match, $to_match_1_0));
  }
 
  /**
  * @access private
  */
  function _verifyDiscoverySingle($endpoint, $to_match)
  {
  // Every type URI that's in the to_match endpoint has to be
  // present in the discovered endpoint.
  foreach ($to_match->type_uris as $type_uri) {
  if (!$endpoint->usesExtension($type_uri)) {
  return new Auth_OpenID_TypeURIMismatch($endpoint,
  "Required type ".$type_uri." not present");
  }
  }
 
  // Fragments do not influence discovery, so we can't compare a
  // claimed identifier with a fragment to discovered
  // information.
  list($defragged_claimed_id, $_) =
  Auth_OpenID::urldefrag($to_match->claimed_id);
 
  if ($defragged_claimed_id != $endpoint->claimed_id) {
  return new Auth_OpenID_FailureResponse($endpoint,
  sprintf('Claimed ID does not match (different subjects!), ' .
  'Expected %s, got %s', $defragged_claimed_id,
  $endpoint->claimed_id));
  }
 
  if ($to_match->getLocalID() != $endpoint->getLocalID()) {
  return new Auth_OpenID_FailureResponse($endpoint,
  sprintf('local_id mismatch. Expected %s, got %s',
  $to_match->getLocalID(), $endpoint->getLocalID()));
  }
 
  // If the server URL is None, this must be an OpenID 1
  // response, because op_endpoint is a required parameter in
  // OpenID 2. In that case, we don't actually care what the
  // discovered server_url is, because signature checking or
  // check_auth should take care of that check for us.
  if ($to_match->server_url === null) {
  if ($to_match->preferredNamespace() != Auth_OpenID_OPENID1_NS) {
  return new Auth_OpenID_FailureResponse($endpoint,
  "Preferred namespace mismatch (bug)");
  }
  } else if ($to_match->server_url != $endpoint->server_url) {
  return new Auth_OpenID_FailureResponse($endpoint,
  sprintf('OP Endpoint mismatch. Expected %s, got %s',
  $to_match->server_url, $endpoint->server_url));
  }
 
  return null;
  }
 
  /**
  * @access private
  */
  function _verifyDiscoveryResultsOpenID2($message, $endpoint)
  {
  $to_match = new Auth_OpenID_ServiceEndpoint();
  $to_match->type_uris = array(Auth_OpenID_TYPE_2_0);
  $to_match->claimed_id = $message->getArg(Auth_OpenID_OPENID2_NS,
  'claimed_id');
 
  $to_match->local_id = $message->getArg(Auth_OpenID_OPENID2_NS,
  'identity');
 
  $to_match->server_url = $message->getArg(Auth_OpenID_OPENID2_NS,
  'op_endpoint');
 
  if ($to_match->server_url === null) {
  return new Auth_OpenID_FailureResponse($endpoint,
  "OP Endpoint URL missing");
  }
 
  // claimed_id and identifier must both be present or both be
  // absent
  if (($to_match->claimed_id === null) &&
  ($to_match->local_id !== null)) {
  return new Auth_OpenID_FailureResponse($endpoint,
  'openid.identity is present without openid.claimed_id');
  }
 
  if (($to_match->claimed_id !== null) &&
  ($to_match->local_id === null)) {
  return new Auth_OpenID_FailureResponse($endpoint,
  'openid.claimed_id is present without openid.identity');
  }
 
  if ($to_match->claimed_id === null) {
  // This is a response without identifiers, so there's
  // really no checking that we can do, so return an
  // endpoint that's for the specified `openid.op_endpoint'
  return Auth_OpenID_ServiceEndpoint::fromOPEndpointURL(
  $to_match->server_url);
  }
 
  if (!$endpoint) {
  // The claimed ID doesn't match, so we have to do
  // discovery again. This covers not using sessions, OP
  // identifier endpoints and responses that didn't match
  // the original request.
  // oidutil.log('No pre-discovered information supplied.')
  return $this->_discoverAndVerify($to_match->claimed_id,
  array($to_match));
  } else {
 
  // The claimed ID matches, so we use the endpoint that we
  // discovered in initiation. This should be the most
  // common case.
  $result = $this->_verifyDiscoverySingle($endpoint, $to_match);
 
  if (Auth_OpenID::isFailure($result)) {
  $endpoint = $this->_discoverAndVerify($to_match->claimed_id,
  array($to_match));
  if (Auth_OpenID::isFailure($endpoint)) {
  return $endpoint;
  }
  }
  }
 
  // The endpoint we return should have the claimed ID from the
  // message we just verified, fragment and all.
  if ($endpoint->claimed_id != $to_match->claimed_id) {
  $endpoint->claimed_id = $to_match->claimed_id;
  }
 
  return $endpoint;
  }
 
  /**
  * @access private
  */
  function _discoverAndVerify($claimed_id, $to_match_endpoints)
  {
  // oidutil.log('Performing discovery on %s' % (claimed_id,))
  list($unused, $services) = call_user_func($this->discoverMethod,
  $claimed_id,
  $this->fetcher);
 
  if (!$services) {
  return new Auth_OpenID_FailureResponse(null,
  sprintf("No OpenID information found at %s",
  $claimed_id));
  }
 
  return $this->_verifyDiscoveryServices($claimed_id, $services,
  $to_match_endpoints);
  }
 
  /**
  * @access private
  */
  function _verifyDiscoveryServices($claimed_id,
  $services, $to_match_endpoints)
  {
  // Search the services resulting from discovery to find one
  // that matches the information from the assertion
 
  foreach ($services as $endpoint) {
  foreach ($to_match_endpoints as $to_match_endpoint) {
  $result = $this->_verifyDiscoverySingle($endpoint,
  $to_match_endpoint);
 
  if (!Auth_OpenID::isFailure($result)) {
  // It matches, so discover verification has
  // succeeded. Return this endpoint.
  return $endpoint;
  }
  }
  }
 
  return new Auth_OpenID_FailureResponse(null,
  sprintf('No matching endpoint found after discovering %s: %s',
  $claimed_id, $result->message));
  }
 
  /**
  * Extract the nonce from an OpenID 1 response. Return the nonce
  * from the BARE_NS since we independently check the return_to
  * arguments are the same as those in the response message.
  *
  * See the openid1_nonce_query_arg_name class variable
  *
  * @returns $nonce The nonce as a string or null
  *
  * @access private
  */
  function _idResGetNonceOpenID1($message, $endpoint)
  {
  return $message->getArg(Auth_OpenID_BARE_NS,
  $this->openid1_nonce_query_arg_name);
  }
 
  /**
  * @access private
  */
  function _idResCheckNonce($message, $endpoint)
  {
  if ($message->isOpenID1()) {
  // This indicates that the nonce was generated by the consumer
  $nonce = $this->_idResGetNonceOpenID1($message, $endpoint);
  $server_url = '';
  } else {
  $nonce = $message->getArg(Auth_OpenID_OPENID2_NS,
  'response_nonce');
 
  $server_url = $endpoint->server_url;
  }
 
  if ($nonce === null) {
  return new Auth_OpenID_FailureResponse($endpoint,
  "Nonce missing from response");
  }
 
  $parts = Auth_OpenID_splitNonce($nonce);
 
  if ($parts === null) {
  return new Auth_OpenID_FailureResponse($endpoint,
  "Malformed nonce in response");
  }
 
  list($timestamp, $salt) = $parts;
 
  if (!$this->store->useNonce($server_url, $timestamp, $salt)) {
  return new Auth_OpenID_FailureResponse($endpoint,
  "Nonce already used or out of range");
  }
 
  return null;
  }
 
  /**
  * @access private
  */
  function _idResCheckForFields($message)
  {
  $basic_fields = array('return_to', 'assoc_handle', 'sig', 'signed');
  $basic_sig_fields = array('return_to', 'identity');
 
  $require_fields = array(
  Auth_OpenID_OPENID2_NS => array_merge($basic_fields,
  array('op_endpoint')),
 
  Auth_OpenID_OPENID1_NS => array_merge($basic_fields,
  array('identity'))
  );
 
  $require_sigs = array(
  Auth_OpenID_OPENID2_NS => array_merge($basic_sig_fields,
  array('response_nonce',
  'claimed_id',
  'assoc_handle',
  'op_endpoint')),
  Auth_OpenID_OPENID1_NS => array_merge($basic_sig_fields,
  array('nonce'))
  );
 
  foreach ($require_fields[$message->getOpenIDNamespace()] as $field) {
  if (!$message->hasKey(Auth_OpenID_OPENID_NS, $field)) {
  return new Auth_OpenID_FailureResponse(null,
  "Missing required field '".$field."'");
  }
  }
 
  $signed_list_str = $message->getArg(Auth_OpenID_OPENID_NS,
  'signed',
  Auth_OpenID_NO_DEFAULT);
  if (Auth_OpenID::isFailure($signed_list_str)) {
  return $signed_list_str;
  }
  $signed_list = explode(',', $signed_list_str);
 
  foreach ($require_sigs[$message->getOpenIDNamespace()] as $field) {
  // Field is present and not in signed list
  if ($message->hasKey(Auth_OpenID_OPENID_NS, $field) &&
  (!in_array($field, $signed_list))) {
  return new Auth_OpenID_FailureResponse(null,
  "'".$field."' not signed");
  }
  }
 
  return null;
  }
 
  /**
  * @access private
  */
  function _checkAuth($message, $server_url)
  {
  $request = $this->_createCheckAuthRequest($message);
  if ($request === null) {
  return false;
  }
 
  $resp_message = $this->_makeKVPost($request, $server_url);
  if (($resp_message === null) ||
  (is_a($resp_message, 'Auth_OpenID_ServerErrorContainer'))) {
  return false;
  }
 
  return $this->_processCheckAuthResponse($resp_message, $server_url);
  }
 
  /**
  * @access private
  */
  function _createCheckAuthRequest($message)
  {
  $signed = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
  if ($signed) {
  foreach (explode(',', $signed) as $k) {
  $value = $message->getAliasedArg($k);
  if ($value === null) {
  return null;
  }
  }
  }
  $ca_message = $message->copy();
  $ca_message->setArg(Auth_OpenID_OPENID_NS, 'mode',
  'check_authentication');
  return $ca_message;
  }
 
  /**
  * @access private
  */
  function _processCheckAuthResponse($response, $server_url)
  {
  $is_valid = $response->getArg(Auth_OpenID_OPENID_NS, 'is_valid',
  'false');
 
  $invalidate_handle = $response->getArg(Auth_OpenID_OPENID_NS,
  'invalidate_handle');
 
  if ($invalidate_handle !== null) {
  $this->store->removeAssociation($server_url,
  $invalidate_handle);
  }
 
  if ($is_valid == 'true') {
  return true;
  }
 
  return false;
  }
 
  /**
  * Adapt a POST response to a Message.
  *
  * @param $response Result of a POST to an OpenID endpoint.
  *
  * @access private
  */
  static function _httpResponseToMessage($response, $server_url)
  {
  // Should this function be named Message.fromHTTPResponse instead?
  $response_message = Auth_OpenID_Message::fromKVForm($response->body);
 
  if ($response->status == 400) {
  return Auth_OpenID_ServerErrorContainer::fromMessage(
  $response_message);
  } else if ($response->status != 200 and $response->status != 206) {
  return null;
  }
 
  return $response_message;
  }
 
  /**
  * @access private
  */
  function _makeKVPost($message, $server_url)
  {
  $body = $message->toURLEncoded();
  $resp = $this->fetcher->post($server_url, $body);
 
  if ($resp === null) {
  return null;
  }
 
  return $this->_httpResponseToMessage($resp, $server_url);
  }
 
  /**
  * @access private
  */
  function _getAssociation($endpoint)
  {
  if (!$this->_use_assocs) {
  return null;
  }
 
  $assoc = $this->store->getAssociation($endpoint->server_url);
 
  if (($assoc === null) ||
  ($assoc->getExpiresIn() <= 0)) {
 
  $assoc = $this->_negotiateAssociation($endpoint);
 
  if ($assoc !== null) {
  $this->store->storeAssociation($endpoint->server_url,
  $assoc);
  }
  }
 
  return $assoc;
  }
 
  /**
  * Handle ServerErrors resulting from association requests.
  *
  * @return $result If server replied with an C{unsupported-type}
  * error, return a tuple of supported C{association_type},
  * C{session_type}. Otherwise logs the error and returns null.
  *
  * @access private
  */
  function _extractSupportedAssociationType($server_error, $endpoint,
  $assoc_type)
  {
  // Any error message whose code is not 'unsupported-type'
  // should be considered a total failure.
  if (($server_error->error_code != 'unsupported-type') ||
  ($server_error->message->isOpenID1())) {
  return null;
  }
 
  // The server didn't like the association/session type that we
  // sent, and it sent us back a message that might tell us how
  // to handle it.
 
  // Extract the session_type and assoc_type from the error
  // message
  $assoc_type = $server_error->message->getArg(Auth_OpenID_OPENID_NS,
  'assoc_type');
 
  $session_type = $server_error->message->getArg(Auth_OpenID_OPENID_NS,
  'session_type');
 
  if (($assoc_type === null) || ($session_type === null)) {
  return null;
  } else if (!$this->negotiator->isAllowed($assoc_type,
  $session_type)) {
  return null;
  } else {
  return array($assoc_type, $session_type);
  }
  }
 
  /**
  * @access private
  */
  function _negotiateAssociation($endpoint)
  {
  // Get our preferred session/association type from the negotiatior.
  list($assoc_type, $session_type) = $this->negotiator->getAllowedType();
 
  $assoc = $this->_requestAssociation(
  $endpoint, $assoc_type, $session_type);
 
  if (Auth_OpenID::isFailure($assoc)) {
  return null;
  }
 
  if (is_a($assoc, 'Auth_OpenID_ServerErrorContainer')) {
  $why = $assoc;
 
  $supportedTypes = $this->_extractSupportedAssociationType(
  $why, $endpoint, $assoc_type);
 
  if ($supportedTypes !== null) {
  list($assoc_type, $session_type) = $supportedTypes;
 
  // Attempt to create an association from the assoc_type
  // and session_type that the server told us it
  // supported.
  $assoc = $this->_requestAssociation(
  $endpoint, $assoc_type, $session_type);
 
  if (is_a($assoc, 'Auth_OpenID_ServerErrorContainer')) {
  // Do not keep trying, since it rejected the
  // association type that it told us to use.
  // oidutil.log('Server %s refused its suggested association
  // 'type: session_type=%s, assoc_type=%s'
  // % (endpoint.server_url, session_type,
  // assoc_type))
  return null;
  } else {
  return $assoc;
  }
  } else {
  return null;
  }
  } else {
  return $assoc;
  }
  }
 
  /**
  * @access private
  */
  function _requestAssociation($endpoint, $assoc_type, $session_type)
  {
  list($assoc_session, $args) = $this->_createAssociateRequest(
  $endpoint, $assoc_type, $session_type);
 
  $response_message = $this->_makeKVPost($args, $endpoint->server_url);
 
  if ($response_message === null) {
  // oidutil.log('openid.associate request failed: %s' % (why[0],))
  return null;
  } else if (is_a($response_message,
  'Auth_OpenID_ServerErrorContainer')) {
  return $response_message;
  }
 
  return $this->_extractAssociation($response_message, $assoc_session);
  }
 
  /**
  * @access private
  */
  function _extractAssociation($assoc_response, $assoc_session)
  {
  // Extract the common fields from the response, raising an
  // exception if they are not found
  $assoc_type = $assoc_response->getArg(
  Auth_OpenID_OPENID_NS, 'assoc_type',
  Auth_OpenID_NO_DEFAULT);
 
  if (Auth_OpenID::isFailure($assoc_type)) {
  return $assoc_type;
  }
 
  $assoc_handle = $assoc_response->getArg(
  Auth_OpenID_OPENID_NS, 'assoc_handle',
  Auth_OpenID_NO_DEFAULT);
 
  if (Auth_OpenID::isFailure($assoc_handle)) {
  return $assoc_handle;
  }
 
  // expires_in is a base-10 string. The Python parsing will
  // accept literals that have whitespace around them and will
  // accept negative values. Neither of these are really in-spec,
  // but we think it's OK to accept them.
  $expires_in_str = $assoc_response->getArg(
  Auth_OpenID_OPENID_NS, 'expires_in',
  Auth_OpenID_NO_DEFAULT);
 
  if (Auth_OpenID::isFailure($expires_in_str)) {
  return $expires_in_str;
  }
 
  $expires_in = Auth_OpenID::intval($expires_in_str);
  if ($expires_in === false) {
 
  $err = sprintf("Could not parse expires_in from association ".
  "response %s", print_r($assoc_response, true));
  return new Auth_OpenID_FailureResponse(null, $err);
  }
 
  // OpenID 1 has funny association session behaviour.
  if ($assoc_response->isOpenID1()) {
  $session_type = $this->_getOpenID1SessionType($assoc_response);
  } else {
  $session_type = $assoc_response->getArg(
  Auth_OpenID_OPENID2_NS, 'session_type',
  Auth_OpenID_NO_DEFAULT);
 
  if (Auth_OpenID::isFailure($session_type)) {
  return $session_type;
  }
  }
 
  // Session type mismatch
  if ($assoc_session->session_type != $session_type) {
  if ($assoc_response->isOpenID1() &&
  ($session_type == 'no-encryption')) {
  // In OpenID 1, any association request can result in
  // a 'no-encryption' association response. Setting
  // assoc_session to a new no-encryption session should
  // make the rest of this function work properly for
  // that case.
  $assoc_session = new Auth_OpenID_PlainTextConsumerSession();
  } else {
  // Any other mismatch, regardless of protocol version
  // results in the failure of the association session
  // altogether.
  return null;
  }
  }
 
  // Make sure assoc_type is valid for session_type
  if (!in_array($assoc_type, $assoc_session->allowed_assoc_types)) {
  return null;
  }
 
  // Delegate to the association session to extract the secret
  // from the response, however is appropriate for that session
  // type.
  $secret = $assoc_session->extractSecret($assoc_response);
 
  if ($secret === null) {
  return null;
  }
 
  return Auth_OpenID_Association::fromExpiresIn(
  $expires_in, $assoc_handle, $secret, $assoc_type);
  }
 
  /**
  * @access private
  */
  function _createAssociateRequest($endpoint, $assoc_type, $session_type)
  {
  if (array_key_exists($session_type, $this->session_types)) {
  $session_type_class = $this->session_types[$session_type];
 
  if (is_callable($session_type_class)) {
  $assoc_session = $session_type_class();
  } else {
  $assoc_session = new $session_type_class();
  }
  } else {
  return null;
  }
 
  $args = array(
  'mode' => 'associate',
  'assoc_type' => $assoc_type);
 
  if (!$endpoint->compatibilityMode()) {
  $args['ns'] = Auth_OpenID_OPENID2_NS;
  }
 
  // Leave out the session type if we're in compatibility mode
  // *and* it's no-encryption.
  if ((!$endpoint->compatibilityMode()) ||
  ($assoc_session->session_type != 'no-encryption')) {
  $args['session_type'] = $assoc_session->session_type;
  }
 
  $args = array_merge($args, $assoc_session->getRequest());
  $message = Auth_OpenID_Message::fromOpenIDArgs($args);
  return array($assoc_session, $message);
  }
 
  /**
  * Given an association response message, extract the OpenID 1.X
  * session type.
  *
  * This function mostly takes care of the 'no-encryption' default
  * behavior in OpenID 1.
  *
  * If the association type is plain-text, this function will
  * return 'no-encryption'
  *
  * @access private
  * @return $typ The association type for this message
  */
  function _getOpenID1SessionType($assoc_response)
  {
  // If it's an OpenID 1 message, allow session_type to default
  // to None (which signifies "no-encryption")
  $session_type = $assoc_response->getArg(Auth_OpenID_OPENID1_NS,
  'session_type');
 
  // Handle the differences between no-encryption association
  // respones in OpenID 1 and 2:
 
  // no-encryption is not really a valid session type for OpenID
  // 1, but we'll accept it anyway, while issuing a warning.
  if ($session_type == 'no-encryption') {
  // oidutil.log('WARNING: OpenID server sent "no-encryption"'
  // 'for OpenID 1.X')
  } else if (($session_type == '') || ($session_type === null)) {
  // Missing or empty session type is the way to flag a
  // 'no-encryption' response. Change the session type to
  // 'no-encryption' so that it can be handled in the same
  // way as OpenID 2 'no-encryption' respones.
  $session_type = 'no-encryption';
  }
 
  return $session_type;
  }
  }
 
  /**
  * This class represents an authentication request from a consumer to
  * an OpenID server.
  *
  * @package OpenID
  */
  class Auth_OpenID_AuthRequest {
 
  /**
  * Initialize an authentication request with the specified token,
  * association, and endpoint.
  *
  * Users of this library should not create instances of this
  * class. Instances of this class are created by the library when
  * needed.
  */
  function Auth_OpenID_AuthRequest($endpoint, $assoc)
  {
  $this->assoc = $assoc;
  $this->endpoint = $endpoint;
  $this->return_to_args = array();
  $this->message = new Auth_OpenID_Message(
  $endpoint->preferredNamespace());
  $this->_anonymous = false;
  }
 
  /**
  * Add an extension to this checkid request.
  *
  * $extension_request: An object that implements the extension
  * request interface for adding arguments to an OpenID message.
  */
  function addExtension($extension_request)
  {
  $extension_request->toMessage($this->message);
  }
 
  /**
  * Add an extension argument to this OpenID authentication
  * request.
  *
  * Use caution when adding arguments, because they will be
  * URL-escaped and appended to the redirect URL, which can easily
  * get quite long.
  *
  * @param string $namespace The namespace for the extension. For
  * example, the simple registration extension uses the namespace
  * 'sreg'.
  *
  * @param string $key The key within the extension namespace. For
  * example, the nickname field in the simple registration
  * extension's key is 'nickname'.
  *
  * @param string $value The value to provide to the server for
  * this argument.
  */
  function addExtensionArg($namespace, $key, $value)
  {
  return $this->message->setArg($namespace, $key, $value);
  }
 
  /**
  * Set whether this request should be made anonymously. If a
  * request is anonymous, the identifier will not be sent in the
  * request. This is only useful if you are making another kind of
  * request with an extension in this request.
  *
  * Anonymous requests are not allowed when the request is made
  * with OpenID 1.
  */
  function setAnonymous($is_anonymous)
  {
  if ($is_anonymous && $this->message->isOpenID1()) {
  return false;
  } else {
  $this->_anonymous = $is_anonymous;
  return true;
  }
  }
 
  /**
  * Produce a {@link Auth_OpenID_Message} representing this
  * request.
  *
  * @param string $realm The URL (or URL pattern) that identifies
  * your web site to the user when she is authorizing it.
  *
  * @param string $return_to The URL that the OpenID provider will
  * send the user back to after attempting to verify her identity.
  *
  * Not specifying a return_to URL means that the user will not be
  * returned to the site issuing the request upon its completion.
  *
  * @param bool $immediate If true, the OpenID provider is to send
  * back a response immediately, useful for behind-the-scenes
  * authentication attempts. Otherwise the OpenID provider may
  * engage the user before providing a response. This is the
  * default case, as the user may need to provide credentials or
  * approve the request before a positive response can be sent.
  */
  function getMessage($realm, $return_to=null, $immediate=false)
  {
  if ($return_to) {
  $return_to = Auth_OpenID::appendArgs($return_to,
  $this->return_to_args);
  } else if ($immediate) {
  // raise ValueError(
  // '"return_to" is mandatory when
  //using "checkid_immediate"')
  return new Auth_OpenID_FailureResponse(null,
  "'return_to' is mandatory when using checkid_immediate");
  } else if ($this->message->isOpenID1()) {
  // raise ValueError('"return_to" is
  // mandatory for OpenID 1 requests')
  return new Auth_OpenID_FailureResponse(null,
  "'return_to' is mandatory for OpenID 1 requests");
  } else if ($this->return_to_args) {
  // raise ValueError('extra "return_to" arguments
  // were specified, but no return_to was specified')
  return new Auth_OpenID_FailureResponse(null,
  "extra 'return_to' arguments where specified, " .
  "but no return_to was specified");
  }
 
  if ($immediate) {
  $mode = 'checkid_immediate';
  } else {
  $mode = 'checkid_setup';
  }
 
  $message = $this->message->copy();
  if ($message->isOpenID1()) {
  $realm_key = 'trust_root';
  } else {
  $realm_key = 'realm';
  }
 
  $message->updateArgs(Auth_OpenID_OPENID_NS,
  array(
  $realm_key => $realm,
  'mode' => $mode,
  'return_to' => $return_to));
 
  if (!$this->_anonymous) {
  if ($this->endpoint->isOPIdentifier()) {
  // This will never happen when we're in compatibility
  // mode, as long as isOPIdentifier() returns False
  // whenever preferredNamespace() returns OPENID1_NS.
  $claimed_id = $request_identity =
  Auth_OpenID_IDENTIFIER_SELECT;
  } else {
  $request_identity = $this->endpoint->getLocalID();
  $claimed_id = $this->endpoint->claimed_id;
  }
 
  // This is true for both OpenID 1 and 2
  $message->setArg(Auth_OpenID_OPENID_NS, 'identity',
  $request_identity);
 
  if ($message->isOpenID2()) {
  $message->setArg(Auth_OpenID_OPENID2_NS, 'claimed_id',
  $claimed_id);
  }
  }
 
  if ($this->assoc) {
  $message->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle',
  $this->assoc->handle);
  }
 
  return $message;
  }
 
  function redirectURL($realm, $return_to = null,
  $immediate = false)
  {
  $message = $this->getMessage($realm, $return_to, $immediate);
 
  if (Auth_OpenID::isFailure($message)) {
  return $message;
  }
 
  return $message->toURL($this->endpoint->server_url);
  }
 
  /**
  * Get html for a form to submit this request to the IDP.
  *
  * form_tag_attrs: An array of attributes to be added to the form
  * tag. 'accept-charset' and 'enctype' have defaults that can be
  * overridden. If a value is supplied for 'action' or 'method', it
  * will be replaced.
  */
  function formMarkup($realm, $return_to=null, $immediate=false,
  $form_tag_attrs=null)
  {
  $message = $this->getMessage($realm, $return_to, $immediate);
 
  if (Auth_OpenID::isFailure($message)) {
  return $message;
  }
 
  return $message->toFormMarkup($this->endpoint->server_url,
  $form_tag_attrs);
  }
 
  /**
  * Get a complete html document that will autosubmit the request
  * to the IDP.
  *
  * Wraps formMarkup. See the documentation for that function.
  */
  function htmlMarkup($realm, $return_to=null, $immediate=false,
  $form_tag_attrs=null)
  {
  $form = $this->formMarkup($realm, $return_to, $immediate,
  $form_tag_attrs);
 
  if (Auth_OpenID::isFailure($form)) {
  return $form;
  }
  return Auth_OpenID::autoSubmitHTML($form);
  }
 
  function shouldSendRedirect()
  {
  return $this->endpoint->compatibilityMode();
  }
  }
 
  /**
  * The base class for responses from the Auth_OpenID_Consumer.
  *
  * @package OpenID
  */
  class Auth_OpenID_ConsumerResponse {
  var $status = null;
 
  function setEndpoint($endpoint)
  {
  $this->endpoint = $endpoint;
  if ($endpoint === null) {
  $this->identity_url = null;
  } else {
  $this->identity_url = $endpoint->claimed_id;
  }
  }
 
  /**
  * Return the display identifier for this response.
  *
  * The display identifier is related to the Claimed Identifier, but the
  * two are not always identical. The display identifier is something the
  * user should recognize as what they entered, whereas the response's
  * claimed identifier (in the identity_url attribute) may have extra
  * information for better persistence.
  *
  * URLs will be stripped of their fragments for display. XRIs will
  * display the human-readable identifier (i-name) instead of the
  * persistent identifier (i-number).
  *
  * Use the display identifier in your user interface. Use
  * identity_url for querying your database or authorization server.
  *
  */
  function getDisplayIdentifier()
  {
  if ($this->endpoint !== null) {
  return $this->endpoint->getDisplayIdentifier();
  }
  return null;
  }
  }
 
  /**
  * A response with a status of Auth_OpenID_SUCCESS. Indicates that
  * this request is a successful acknowledgement from the OpenID server
  * that the supplied URL is, indeed controlled by the requesting
  * agent. This has three relevant attributes:
  *
  * claimed_id - The identity URL that has been authenticated
  *
  * signed_args - The arguments in the server's response that were
  * signed and verified.
  *
  * status - Auth_OpenID_SUCCESS.
  *
  * @package OpenID
  */
  class Auth_OpenID_SuccessResponse extends Auth_OpenID_ConsumerResponse {
  var $status = Auth_OpenID_SUCCESS;
 
  /**
  * @access private
  */
  function Auth_OpenID_SuccessResponse($endpoint, $message, $signed_args=null)
  {
  $this->endpoint = $endpoint;
  $this->identity_url = $endpoint->claimed_id;
  $this->signed_args = $signed_args;
  $this->message = $message;
 
  if ($this->signed_args === null) {
  $this->signed_args = array();
  }
  }
 
  /**
  * Extract signed extension data from the server's response.
  *
  * @param string $prefix The extension namespace from which to
  * extract the extension data.
  */
  function extensionResponse($namespace_uri, $require_signed)
  {
  if ($require_signed) {
  return $this->getSignedNS($namespace_uri);
  } else {
  return $this->message->getArgs($namespace_uri);
  }
  }
 
  function isOpenID1()
  {
  return $this->message->isOpenID1();
  }
 
  function isSigned($ns_uri, $ns_key)
  {
  // Return whether a particular key is signed, regardless of
  // its namespace alias
  return in_array($this->message->getKey($ns_uri, $ns_key),
  $this->signed_args);
  }
 
  function getSigned($ns_uri, $ns_key, $default = null)
  {
  // Return the specified signed field if available, otherwise
  // return default
  if ($this->isSigned($ns_uri, $ns_key)) {
  return $this->message->getArg($ns_uri, $ns_key, $default);
  } else {
  return $default;
  }
  }
 
  function getSignedNS($ns_uri)
  {
  $args = array();
 
  $msg_args = $this->message->getArgs($ns_uri);
  if (Auth_OpenID::isFailure($msg_args)) {
  return null;
  }
 
  foreach ($msg_args as $key => $value) {
  if (!$this->isSigned($ns_uri, $key)) {
  unset($msg_args[$key]);
  }
  }
 
  return $msg_args;
  }
 
  /**
  * Get the openid.return_to argument from this response.
  *
  * This is useful for verifying that this request was initiated by
  * this consumer.
  *
  * @return string $return_to The return_to URL supplied to the
  * server on the initial request, or null if the response did not
  * contain an 'openid.return_to' argument.
  */
  function getReturnTo()
  {
  return $this->getSigned(Auth_OpenID_OPENID_NS, 'return_to');
  }
  }
 
  /**
  * A response with a status of Auth_OpenID_FAILURE. Indicates that the
  * OpenID protocol has failed. This could be locally or remotely
  * triggered. This has three relevant attributes:
  *
  * claimed_id - The identity URL for which authentication was
  * attempted, if it can be determined. Otherwise, null.
  *
  * message - A message indicating why the request failed, if one is
  * supplied. Otherwise, null.
  *
  * status - Auth_OpenID_FAILURE.
  *
  * @package OpenID
  */
  class Auth_OpenID_FailureResponse extends Auth_OpenID_ConsumerResponse {
  var $status = Auth_OpenID_FAILURE;
 
  function Auth_OpenID_FailureResponse($endpoint, $message = null,
  $contact = null, $reference = null)
  {
  $this->setEndpoint($endpoint);
  $this->message = $message;
  $this->contact = $contact;
  $this->reference = $reference;
  }
  }
 
  /**
  * A specific, internal failure used to detect type URI mismatch.
  *
  * @package OpenID
  */
  class Auth_OpenID_TypeURIMismatch extends Auth_OpenID_FailureResponse {
  }
 
  /**
  * Exception that is raised when the server returns a 400 response
  * code to a direct request.
  *
  * @package OpenID
  */
  class Auth_OpenID_ServerErrorContainer {
  function Auth_OpenID_ServerErrorContainer($error_text,
  $error_code,
  $message)
  {
  $this->error_text = $error_text;
  $this->error_code = $error_code;
  $this->message = $message;
  }
 
  /**
  * @access private
  */
  static function fromMessage($message)
  {
  $error_text = $message->getArg(
  Auth_OpenID_OPENID_NS, 'error', '<no error message supplied>');
  $error_code = $message->getArg(Auth_OpenID_OPENID_NS, 'error_code');
  return new Auth_OpenID_ServerErrorContainer($error_text,
  $error_code,
  $message);
  }
  }
 
  /**
  * A response with a status of Auth_OpenID_CANCEL. Indicates that the
  * user cancelled the OpenID authentication request. This has two
  * relevant attributes:
  *
  * claimed_id - The identity URL for which authentication was
  * attempted, if it can be determined. Otherwise, null.
  *
  * status - Auth_OpenID_SUCCESS.
  *
  * @package OpenID
  */
  class Auth_OpenID_CancelResponse extends Auth_OpenID_ConsumerResponse {
  var $status = Auth_OpenID_CANCEL;
 
  function Auth_OpenID_CancelResponse($endpoint)
  {
  $this->setEndpoint($endpoint);
  }
  }
 
  /**
  * A response with a status of Auth_OpenID_SETUP_NEEDED. Indicates
  * that the request was in immediate mode, and the server is unable to
  * authenticate the user without further interaction.
  *
  * claimed_id - The identity URL for which authentication was
  * attempted.
  *
  * setup_url - A URL that can be used to send the user to the server
  * to set up for authentication. The user should be redirected in to
  * the setup_url, either in the current window or in a new browser
  * window. Null in OpenID 2.
  *
  * status - Auth_OpenID_SETUP_NEEDED.
  *
  * @package OpenID
  */
  class Auth_OpenID_SetupNeededResponse extends Auth_OpenID_ConsumerResponse {
  var $status = Auth_OpenID_SETUP_NEEDED;
 
  function Auth_OpenID_SetupNeededResponse($endpoint,
  $setup_url = null)
  {
  $this->setEndpoint($endpoint);
  $this->setup_url = $setup_url;
  }
  }
 
 
 
  <?php
 
  /**
  * OpenID server protocol and logic.
  *
  * Overview
  *
  * An OpenID server must perform three tasks:
  *
  * 1. Examine the incoming request to determine its nature and validity.
  * 2. Make a decision about how to respond to this request.
  * 3. Format the response according to the protocol.
  *
  * The first and last of these tasks may performed by the {@link
  * Auth_OpenID_Server::decodeRequest()} and {@link
  * Auth_OpenID_Server::encodeResponse} methods. Who gets to do the
  * intermediate task -- deciding how to respond to the request -- will
  * depend on what type of request it is.
  *
  * If it's a request to authenticate a user (a 'checkid_setup' or
  * 'checkid_immediate' request), you need to decide if you will assert
  * that this user may claim the identity in question. Exactly how you
  * do that is a matter of application policy, but it generally
  * involves making sure the user has an account with your system and
  * is logged in, checking to see if that identity is hers to claim,
  * and verifying with the user that she does consent to releasing that
  * information to the party making the request.
  *
  * Examine the properties of the {@link Auth_OpenID_CheckIDRequest}
  * object, and if and when you've come to a decision, form a response
  * by calling {@link Auth_OpenID_CheckIDRequest::answer()}.
  *
  * Other types of requests relate to establishing associations between
  * client and server and verifing the authenticity of previous
  * communications. {@link Auth_OpenID_Server} contains all the logic
  * and data necessary to respond to such requests; just pass it to
  * {@link Auth_OpenID_Server::handleRequest()}.
  *
  * OpenID Extensions
  *
  * Do you want to provide other information for your users in addition
  * to authentication? Version 1.2 of the OpenID protocol allows
  * consumers to add extensions to their requests. For example, with
  * sites using the Simple Registration
  * Extension
  * (http://openid.net/specs/openid-simple-registration-extension-1_0.html),
  * a user can agree to have their nickname and e-mail address sent to
  * a site when they sign up.
  *
  * Since extensions do not change the way OpenID authentication works,
  * code to handle extension requests may be completely separate from
  * the {@link Auth_OpenID_Request} class here. But you'll likely want
  * data sent back by your extension to be signed. {@link
  * Auth_OpenID_ServerResponse} provides methods with which you can add
  * data to it which can be signed with the other data in the OpenID
  * signature.
  *
  * For example:
  *
  * <pre> // when request is a checkid_* request
  * $response = $request->answer(true);
  * // this will a signed 'openid.sreg.timezone' parameter to the response
  * response.addField('sreg', 'timezone', 'America/Los_Angeles')</pre>
  *
  * Stores
  *
  * The OpenID server needs to maintain state between requests in order
  * to function. Its mechanism for doing this is called a store. The
  * store interface is defined in Interface.php. Additionally, several
  * concrete store implementations are provided, so that most sites
  * won't need to implement a custom store. For a store backed by flat
  * files on disk, see {@link Auth_OpenID_FileStore}. For stores based
  * on MySQL, SQLite, or PostgreSQL, see the {@link
  * Auth_OpenID_SQLStore} subclasses.
  *
  * Upgrading
  *
  * The keys by which a server looks up associations in its store have
  * changed in version 1.2 of this library. If your store has entries
  * created from version 1.0 code, you should empty it.
  *
  * PHP versions 4 and 5
  *
  * LICENSE: See the COPYING file included in this distribution.
  *
  * @package OpenID
  * @author JanRain, Inc. <openid@janrain.com>
  * @copyright 2005-2008 Janrain, Inc.
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  */
 
  /**
  * Required imports
  */
  require_once "Auth/OpenID.php";
  require_once "Auth/OpenID/Association.php";
  require_once "Auth/OpenID/CryptUtil.php";
  require_once "Auth/OpenID/BigMath.php";
  require_once "Auth/OpenID/DiffieHellman.php";
  require_once "Auth/OpenID/KVForm.php";
  require_once "Auth/OpenID/TrustRoot.php";
  require_once "Auth/OpenID/ServerRequest.php";
  require_once "Auth/OpenID/Message.php";
  require_once "Auth/OpenID/Nonce.php";
 
  define('AUTH_OPENID_HTTP_OK', 200);
  define('AUTH_OPENID_HTTP_REDIRECT', 302);
  define('AUTH_OPENID_HTTP_ERROR', 400);
 
  /**
  * @access private
  */
  global $_Auth_OpenID_Request_Modes;
  $_Auth_OpenID_Request_Modes = array('checkid_setup',
  'checkid_immediate');
 
  /**
  * @access private
  */
  define('Auth_OpenID_ENCODE_KVFORM', 'kfvorm');
 
  /**
  * @access private
  */
  define('Auth_OpenID_ENCODE_URL', 'URL/redirect');
 
  /**
  * @access private
  */
  define('Auth_OpenID_ENCODE_HTML_FORM', 'HTML form');
 
  /**
  * @access private
  */
  function Auth_OpenID_isError($obj, $cls = 'Auth_OpenID_ServerError')
  {
  return is_a($obj, $cls);
  }
 
  /**
  * An error class which gets instantiated and returned whenever an
  * OpenID protocol error occurs. Be prepared to use this in place of
  * an ordinary server response.
  *
  * @package OpenID
  */
  class Auth_OpenID_ServerError {
  /**
  * @access private
  */
  function Auth_OpenID_ServerError($message = null, $text = null,
  $reference = null, $contact = null)
  {
  $this->message = $message;
  $this->text = $text;
  $this->contact = $contact;
  $this->reference = $reference;
  }
 
  function getReturnTo()
  {
  if ($this->message &&
  $this->message->hasKey(Auth_OpenID_OPENID_NS, 'return_to')) {
  return $this->message->getArg(Auth_OpenID_OPENID_NS,
  'return_to');
  } else {
  return null;
  }
  }
 
  /**
  * Returns the return_to URL for the request which caused this
  * error.
  */
  function hasReturnTo()
  {
  return $this->getReturnTo() !== null;
  }
 
  /**
  * Encodes this error's response as a URL suitable for
  * redirection. If the response has no return_to, another
  * Auth_OpenID_ServerError is returned.
  */
  function encodeToURL()
  {
  if (!$this->message) {
  return null;
  }
 
  $msg = $this->toMessage();
  return $msg->toURL($this->getReturnTo());
  }
 
  /**
  * Encodes the response to key-value form. This is a
  * machine-readable format used to respond to messages which came
  * directly from the consumer and not through the user-agent. See
  * the OpenID specification.
  */
  function encodeToKVForm()
  {
  return Auth_OpenID_KVForm::fromArray(
  array('mode' => 'error',
  'error' => $this->toString()));
  }
 
  function toFormMarkup($form_tag_attrs=null)
  {
  $msg = $this->toMessage();
  return $msg->toFormMarkup($this->getReturnTo(), $form_tag_attrs);
  }
 
  function toHTML($form_tag_attrs=null)
  {
  return Auth_OpenID::autoSubmitHTML(
  $this->toFormMarkup($form_tag_attrs));
  }
 
  function toMessage()
  {
  // Generate a Message object for sending to the relying party,
  // after encoding.
  $namespace = $this->message->getOpenIDNamespace();
  $reply = new Auth_OpenID_Message($namespace);
  $reply->setArg(Auth_OpenID_OPENID_NS, 'mode', 'error');
  $reply->setArg(Auth_OpenID_OPENID_NS, 'error', $this->toString());
 
  if ($this->contact !== null) {
  $reply->setArg(Auth_OpenID_OPENID_NS, 'contact', $this->contact);
  }
 
  if ($this->reference !== null) {
  $reply->setArg(Auth_OpenID_OPENID_NS, 'reference',
  $this->reference);
  }
 
  return $reply;
  }
 
  /**
  * Returns one of Auth_OpenID_ENCODE_URL,
  * Auth_OpenID_ENCODE_KVFORM, or null, depending on the type of
  * encoding expected for this error's payload.
  */
  function whichEncoding()
  {
  global $_Auth_OpenID_Request_Modes;
 
  if ($this->hasReturnTo()) {
  if ($this->message->isOpenID2() &&
  (strlen($this->encodeToURL()) >
  Auth_OpenID_OPENID1_URL_LIMIT)) {
  return Auth_OpenID_ENCODE_HTML_FORM;
  } else {
  return Auth_OpenID_ENCODE_URL;
  }
  }
 
  if (!$this->message) {
  return null;
  }
 
  $mode = $this->message->getArg(Auth_OpenID_OPENID_NS,
  'mode');
 
  if ($mode) {
  if (!in_array($mode, $_Auth_OpenID_Request_Modes)) {
  return Auth_OpenID_ENCODE_KVFORM;
  }
  }
  return null;
  }
 
  /**
  * Returns this error message.
  */
  function toString()
  {
  if ($this->text) {
  return $this->text;
  } else {
  return get_class($this) . " error";
  }
  }
  }
 
  /**
  * Error returned by the server code when a return_to is absent from a
  * request.
  *
  * @package OpenID
  */
  class Auth_OpenID_NoReturnToError extends Auth_OpenID_ServerError {
  function Auth_OpenID_NoReturnToError($message = null,
  $text = "No return_to URL available")
  {
  parent::Auth_OpenID_ServerError($message, $text);
  }
 
  function toString()
  {
  return "No return_to available";
  }
  }
 
  /**
  * An error indicating that the return_to URL is malformed.
  *
  * @package OpenID
  */
  class Auth_OpenID_MalformedReturnURL extends Auth_OpenID_ServerError {
  function Auth_OpenID_MalformedReturnURL($message, $return_to)
  {
  $this->return_to = $return_to;
  parent::Auth_OpenID_ServerError($message, "malformed return_to URL");
  }
  }
 
  /**
  * This error is returned when the trust_root value is malformed.
  *
  * @package OpenID
  */
  class Auth_OpenID_MalformedTrustRoot extends Auth_OpenID_ServerError {
  function Auth_OpenID_MalformedTrustRoot($message = null,
  $text = "Malformed trust root")
  {
  parent::Auth_OpenID_ServerError($message, $text);
  }
 
  function toString()
  {
  return "Malformed trust root";
  }
  }
 
  /**
  * The base class for all server request classes.
  *
  * @package OpenID
  */
  class Auth_OpenID_Request {
  var $mode = null;
  }
 
  /**
  * A request to verify the validity of a previous response.
  *
  * @package OpenID
  */
  class Auth_OpenID_CheckAuthRequest extends Auth_OpenID_Request {
  var $mode = "check_authentication";
  var $invalidate_handle = null;
 
  function Auth_OpenID_CheckAuthRequest($assoc_handle, $signed,
  $invalidate_handle = null)
  {
  $this->assoc_handle = $assoc_handle;
  $this->signed = $signed;
  if ($invalidate_handle !== null) {
  $this->invalidate_handle = $invalidate_handle;
  }
  $this->namespace = Auth_OpenID_OPENID2_NS;
  $this->message = null;
  }
 
  static function fromMessage($message, $server=null)
  {
  $required_keys = array('assoc_handle', 'sig', 'signed');
 
  foreach ($required_keys as $k) {
  if (!$message->getArg(Auth_OpenID_OPENID_NS, $k)) {
  return new Auth_OpenID_ServerError($message,
  sprintf("%s request missing required parameter %s from \
  query", "check_authentication", $k));
  }
  }
 
  $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS, 'assoc_handle');
  $sig = $message->getArg(Auth_OpenID_OPENID_NS, 'sig');
 
  $signed_list = $message->getArg(Auth_OpenID_OPENID_NS, 'signed');
  $signed_list = explode(",", $signed_list);
 
  $signed = $message;
  if ($signed->hasKey(Auth_OpenID_OPENID_NS, 'mode')) {
  $signed->setArg(Auth_OpenID_OPENID_NS, 'mode', 'id_res');
  }
 
  $result = new Auth_OpenID_CheckAuthRequest($assoc_handle, $signed);
  $result->message = $message;
  $result->sig = $sig;
  $result->invalidate_handle = $message->getArg(Auth_OpenID_OPENID_NS,
  'invalidate_handle');
  return $result;
  }
 
  function answer($signatory)
  {
  $is_valid = $signatory->verify($this->assoc_handle, $this->signed);
 
  // Now invalidate that assoc_handle so it this checkAuth
  // message cannot be replayed.
  $signatory->invalidate($this->assoc_handle, true);
  $response = new Auth_OpenID_ServerResponse($this);
 
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'is_valid',
  ($is_valid ? "true" : "false"));
 
  if ($this->invalidate_handle) {
  $assoc = $signatory->getAssociation($this->invalidate_handle,
  false);
  if (!$assoc) {
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'invalidate_handle',
  $this->invalidate_handle);
  }
  }
  return $response;
  }
  }
 
  /**
  * A class implementing plaintext server sessions.
  *
  * @package OpenID
  */
  class Auth_OpenID_PlainTextServerSession {
  /**
  * An object that knows how to handle association requests with no
  * session type.
  */
  var $session_type = 'no-encryption';
  var $needs_math = false;
  var $allowed_assoc_types = array('HMAC-SHA1', 'HMAC-SHA256');
 
  static function fromMessage($unused_request)
  {
  return new Auth_OpenID_PlainTextServerSession();
  }
 
  function answer($secret)
  {
  return array('mac_key' => base64_encode($secret));
  }
  }
 
  /**
  * A class implementing DH-SHA1 server sessions.
  *
  * @package OpenID
  */
  class Auth_OpenID_DiffieHellmanSHA1ServerSession {
  /**
  * An object that knows how to handle association requests with
  * the Diffie-Hellman session type.
  */
 
  var $session_type = 'DH-SHA1';
  var $needs_math = true;
  var $allowed_assoc_types = array('HMAC-SHA1');
  var $hash_func = 'Auth_OpenID_SHA1';
 
  function Auth_OpenID_DiffieHellmanSHA1ServerSession($dh, $consumer_pubkey)
  {
  $this->dh = $dh;
  $this->consumer_pubkey = $consumer_pubkey;
  }
 
  static function getDH($message)
  {
  $dh_modulus = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_modulus');
  $dh_gen = $message->getArg(Auth_OpenID_OPENID_NS, 'dh_gen');
 
  if ((($dh_modulus === null) && ($dh_gen !== null)) ||
  (($dh_gen === null) && ($dh_modulus !== null))) {
 
  if ($dh_modulus === null) {
  $missing = 'modulus';
  } else {
  $missing = 'generator';
  }
 
  return new Auth_OpenID_ServerError($message,
  'If non-default modulus or generator is '.
  'supplied, both must be supplied. Missing '.
  $missing);
  }
 
  $lib = Auth_OpenID_getMathLib();
 
  if ($dh_modulus || $dh_gen) {
  $dh_modulus = $lib->base64ToLong($dh_modulus);
  $dh_gen = $lib->base64ToLong($dh_gen);
  if ($lib->cmp($dh_modulus, 0) == 0 ||
  $lib->cmp($dh_gen, 0) == 0) {
  return new Auth_OpenID_ServerError(
  $message, "Failed to parse dh_mod or dh_gen");
  }
  $dh = new Auth_OpenID_DiffieHellman($dh_modulus, $dh_gen);
  } else {
  $dh = new Auth_OpenID_DiffieHellman();
  }
 
  $consumer_pubkey = $message->getArg(Auth_OpenID_OPENID_NS,
  'dh_consumer_public');
  if ($consumer_pubkey === null) {
  return new Auth_OpenID_ServerError($message,
  'Public key for DH-SHA1 session '.
  'not found in query');
  }
 
  $consumer_pubkey =
  $lib->base64ToLong($consumer_pubkey);
 
  if ($consumer_pubkey === false) {
  return new Auth_OpenID_ServerError($message,
  "dh_consumer_public is not base64");
  }
 
  return array($dh, $consumer_pubkey);
  }
 
  static function fromMessage($message)
  {
  $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
 
  if (is_a($result, 'Auth_OpenID_ServerError')) {
  return $result;
  } else {
  list($dh, $consumer_pubkey) = $result;
  return new Auth_OpenID_DiffieHellmanSHA1ServerSession($dh,
  $consumer_pubkey);
  }
  }
 
  function answer($secret)
  {
  $lib = Auth_OpenID_getMathLib();
  $mac_key = $this->dh->xorSecret($this->consumer_pubkey, $secret,
  $this->hash_func);
  return array(
  'dh_server_public' =>
  $lib->longToBase64($this->dh->public),
  'enc_mac_key' => base64_encode($mac_key));
  }
  }
 
  /**
  * A class implementing DH-SHA256 server sessions.
  *
  * @package OpenID
  */
  class Auth_OpenID_DiffieHellmanSHA256ServerSession
  extends Auth_OpenID_DiffieHellmanSHA1ServerSession {
 
  var $session_type = 'DH-SHA256';
  var $hash_func = 'Auth_OpenID_SHA256';
  var $allowed_assoc_types = array('HMAC-SHA256');
 
  static function fromMessage($message)
  {
  $result = Auth_OpenID_DiffieHellmanSHA1ServerSession::getDH($message);
 
  if (is_a($result, 'Auth_OpenID_ServerError')) {
  return $result;
  } else {
  list($dh, $consumer_pubkey) = $result;
  return new Auth_OpenID_DiffieHellmanSHA256ServerSession($dh,
  $consumer_pubkey);
  }
  }
  }
 
  /**
  * A request to associate with the server.
  *
  * @package OpenID
  */
  class Auth_OpenID_AssociateRequest extends Auth_OpenID_Request {
  var $mode = "associate";
 
  static function getSessionClasses()
  {
  return array(
  'no-encryption' => 'Auth_OpenID_PlainTextServerSession',
  'DH-SHA1' => 'Auth_OpenID_DiffieHellmanSHA1ServerSession',
  'DH-SHA256' => 'Auth_OpenID_DiffieHellmanSHA256ServerSession');
  }
 
  function Auth_OpenID_AssociateRequest($session, $assoc_type)
  {
  $this->session = $session;
  $this->namespace = Auth_OpenID_OPENID2_NS;
  $this->assoc_type = $assoc_type;
  }
 
  static function fromMessage($message, $server=null)
  {
  if ($message->isOpenID1()) {
  $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
  'session_type');
 
  if ($session_type == 'no-encryption') {
  // oidutil.log('Received OpenID 1 request with a no-encryption '
  // 'assocaition session type. Continuing anyway.')
  } else if (!$session_type) {
  $session_type = 'no-encryption';
  }
  } else {
  $session_type = $message->getArg(Auth_OpenID_OPENID_NS,
  'session_type');
  if ($session_type === null) {
  return new Auth_OpenID_ServerError($message,
  "session_type missing from request");
  }
  }
 
  $session_class = Auth_OpenID::arrayGet(
  Auth_OpenID_AssociateRequest::getSessionClasses(),
  $session_type);
 
  if ($session_class === null) {
  return new Auth_OpenID_ServerError($message,
  "Unknown session type " .
  $session_type);
  }
 
  $session = call_user_func(array($session_class, 'fromMessage'),
  $message);
  if (is_a($session, 'Auth_OpenID_ServerError')) {
  return $session;
  }
 
  $assoc_type = $message->getArg(Auth_OpenID_OPENID_NS,
  'assoc_type', 'HMAC-SHA1');
 
  if (!in_array($assoc_type, $session->allowed_assoc_types)) {
  $fmt = "Session type %s does not support association type %s";
  return new Auth_OpenID_ServerError($message,
  sprintf($fmt, $session_type, $assoc_type));
  }
 
  $obj = new Auth_OpenID_AssociateRequest($session, $assoc_type);
  $obj->message = $message;
  $obj->namespace = $message->getOpenIDNamespace();
  return $obj;
  }
 
  function answer($assoc)
  {
  $response = new Auth_OpenID_ServerResponse($this);
  $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
  array(
  'expires_in' => sprintf('%d', $assoc->getExpiresIn()),
  'assoc_type' => $this->assoc_type,
  'assoc_handle' => $assoc->handle));
 
  $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
  $this->session->answer($assoc->secret));
 
  if (! ($this->session->session_type == 'no-encryption'
  && $this->message->isOpenID1())) {
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'session_type',
  $this->session->session_type);
  }
 
  return $response;
  }
 
  function answerUnsupported($text_message,
  $preferred_association_type=null,
  $preferred_session_type=null)
  {
  if ($this->message->isOpenID1()) {
  return new Auth_OpenID_ServerError($this->message);
  }
 
  $response = new Auth_OpenID_ServerResponse($this);
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'error_code', 'unsupported-type');
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'error', $text_message);
 
  if ($preferred_association_type) {
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'assoc_type',
  $preferred_association_type);
  }
 
  if ($preferred_session_type) {
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'session_type',
  $preferred_session_type);
  }
  $response->code = AUTH_OPENID_HTTP_ERROR;
  return $response;
  }
  }
 
  /**
  * A request to confirm the identity of a user.
  *
  * @package OpenID
  */
  class Auth_OpenID_CheckIDRequest extends Auth_OpenID_Request {
  /**
  * Return-to verification callback. Default is
  * Auth_OpenID_verifyReturnTo from TrustRoot.php.
  */
  var $verifyReturnTo = 'Auth_OpenID_verifyReturnTo';
 
  /**
  * The mode of this request.
  */
  var $mode = "checkid_setup"; // or "checkid_immediate"
 
  /**
  * Whether this request is for immediate mode.
  */
  var $immediate = false;
 
  /**
  * The trust_root value for this request.
  */
  var $trust_root = null;
 
  /**
  * The OpenID namespace for this request.
  * deprecated since version 2.0.2
  */
  var $namespace;
 
  static function make($message, $identity, $return_to, $trust_root = null,
  $immediate = false, $assoc_handle = null, $server = null)
  {
  if ($server === null) {
  return new Auth_OpenID_ServerError($message,
  "server must not be null");
  }
 
  if ($return_to &&
  !Auth_OpenID_TrustRoot::_parse($return_to)) {
  return new Auth_OpenID_MalformedReturnURL($message, $return_to);
  }
 
  $r = new Auth_OpenID_CheckIDRequest($identity, $return_to,
  $trust_root, $immediate,
  $assoc_handle, $server);
 
  $r->namespace = $message->getOpenIDNamespace();
  $r->message = $message;
 
  if (!$r->trustRootValid()) {
  return new Auth_OpenID_UntrustedReturnURL($message,
  $return_to,
  $trust_root);
  } else {
  return $r;
  }
  }
 
  function Auth_OpenID_CheckIDRequest($identity, $return_to,
  $trust_root = null, $immediate = false,
  $assoc_handle = null, $server = null,
  $claimed_id = null)
  {
  $this->namespace = Auth_OpenID_OPENID2_NS;
  $this->assoc_handle = $assoc_handle;
  $this->identity = $identity;
  if ($claimed_id === null) {
  $this->claimed_id = $identity;
  } else {
  $this->claimed_id = $claimed_id;
  }
  $this->return_to = $return_to;
  $this->trust_root = $trust_root;
  $this->server = $server;
 
  if ($immediate) {
  $this->immediate = true;
  $this->mode = "checkid_immediate";
  } else {
  $this->immediate = false;
  $this->mode = "checkid_setup";
  }
  }
 
  function equals($other)
  {
  return (
  (is_a($other, 'Auth_OpenID_CheckIDRequest')) &&
  ($this->namespace == $other->namespace) &&
  ($this->assoc_handle == $other->assoc_handle) &&
  ($this->identity == $other->identity) &&
  ($this->claimed_id == $other->claimed_id) &&
  ($this->return_to == $other->return_to) &&
  ($this->trust_root == $other->trust_root));
  }
 
  /*
  * Does the relying party publish the return_to URL for this
  * response under the realm? It is up to the provider to set a
  * policy for what kinds of realms should be allowed. This
  * return_to URL verification reduces vulnerability to data-theft
  * attacks based on open proxies, corss-site-scripting, or open
  * redirectors.
  *
  * This check should only be performed after making sure that the
  * return_to URL matches the realm.
  *
  * @return true if the realm publishes a document with the
  * return_to URL listed, false if not or if discovery fails
  */
  function returnToVerified()
  {
  $fetcher = Auth_Yadis_Yadis::getHTTPFetcher();
  return call_user_func_array($this->verifyReturnTo,
  array($this->trust_root, $this->return_to, $fetcher));
  }
 
  static function fromMessage($message, $server)
  {
  $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
  $immediate = null;
 
  if ($mode == "checkid_immediate") {
  $immediate = true;
  $mode = "checkid_immediate";
  } else {
  $immediate = false;
  $mode = "checkid_setup";
  }
 
  $return_to = $message->getArg(Auth_OpenID_OPENID_NS,
  'return_to');
 
  if (($message->isOpenID1()) &&
  (!$return_to)) {
  $fmt = "Missing required field 'return_to' from checkid request";
  return new Auth_OpenID_ServerError($message, $fmt);
  }
 
  $identity = $message->getArg(Auth_OpenID_OPENID_NS,
  'identity');
  $claimed_id = $message->getArg(Auth_OpenID_OPENID_NS, 'claimed_id');
  if ($message->isOpenID1()) {
  if ($identity === null) {
  $s = "OpenID 1 message did not contain openid.identity";
  return new Auth_OpenID_ServerError($message, $s);
  }
  } else {
  if ($identity && !$claimed_id) {
  $s = "OpenID 2.0 message contained openid.identity but not " .
  "claimed_id";
  return new Auth_OpenID_ServerError($message, $s);
  } else if ($claimed_id && !$identity) {
  $s = "OpenID 2.0 message contained openid.claimed_id " .
  "but not identity";
  return new Auth_OpenID_ServerError($message, $s);
  }
  }
 
  // There's a case for making self.trust_root be a TrustRoot
  // here. But if TrustRoot isn't currently part of the
  // "public" API, I'm not sure it's worth doing.
  if ($message->isOpenID1()) {
  $trust_root_param = 'trust_root';
  } else {
  $trust_root_param = 'realm';
  }
  $trust_root = $message->getArg(Auth_OpenID_OPENID_NS,
  $trust_root_param);
  if (! $trust_root) {
  $trust_root = $return_to;
  }
 
  if (! $message->isOpenID1() &&
  ($return_to === null) &&
  ($trust_root === null)) {
  return new Auth_OpenID_ServerError($message,
  "openid.realm required when openid.return_to absent");
  }
 
  $assoc_handle = $message->getArg(Auth_OpenID_OPENID_NS,
  'assoc_handle');
 
  $obj = Auth_OpenID_CheckIDRequest::make($message,
  $identity,
  $return_to,
  $trust_root,
  $immediate,
  $assoc_handle,
  $server);
 
  if (is_a($obj, 'Auth_OpenID_ServerError')) {
  return $obj;
  }
 
  $obj->claimed_id = $claimed_id;
 
  return $obj;
  }
 
  function idSelect()
  {
  // Is the identifier to be selected by the IDP?
  // So IDPs don't have to import the constant
  return $this->identity == Auth_OpenID_IDENTIFIER_SELECT;
  }
 
  function trustRootValid()
  {
  if (!$this->trust_root) {
  return true;
  }
 
  $tr = Auth_OpenID_TrustRoot::_parse($this->trust_root);
  if ($tr === false) {
  return new Auth_OpenID_MalformedTrustRoot($this->message,
  $this->trust_root);
  }
 
  if ($this->return_to !== null) {
  return Auth_OpenID_TrustRoot::match($this->trust_root,
  $this->return_to);
  } else {
  return true;
  }
  }
 
  /**
  * Respond to this request. Return either an
  * {@link Auth_OpenID_ServerResponse} or
  * {@link Auth_OpenID_ServerError}.
  *
  * @param bool $allow Allow this user to claim this identity, and
  * allow the consumer to have this information?
  *
  * @param string $server_url DEPRECATED. Passing $op_endpoint to
  * the {@link Auth_OpenID_Server} constructor makes this optional.
  *
  * When an OpenID 1.x immediate mode request does not succeed, it
  * gets back a URL where the request may be carried out in a
  * not-so-immediate fashion. Pass my URL in here (the fully
  * qualified address of this server's endpoint, i.e.
  * http://example.com/server), and I will use it as a base for the
  * URL for a new request.
  *
  * Optional for requests where {@link $immediate} is false or
  * $allow is true.
  *
  * @param string $identity The OP-local identifier to answer with.
  * Only for use when the relying party requested identifier
  * selection.
  *
  * @param string $claimed_id The claimed identifier to answer
  * with, for use with identifier selection in the case where the
  * claimed identifier and the OP-local identifier differ,
  * i.e. when the claimed_id uses delegation.
  *
  * If $identity is provided but this is not, $claimed_id will
  * default to the value of $identity. When answering requests
  * that did not ask for identifier selection, the response
  * $claimed_id will default to that of the request.
  *
  * This parameter is new in OpenID 2.0.
  *
  * @return mixed
  */
  function answer($allow, $server_url = null, $identity = null,
  $claimed_id = null)
  {
  if (!$this->return_to) {
  return new Auth_OpenID_NoReturnToError();
  }
 
  if (!$server_url) {
  if ((!$this->message->isOpenID1()) &&
  (!$this->server->op_endpoint)) {
  return new Auth_OpenID_ServerError(null,
  "server should be constructed with op_endpoint to " .
  "respond to OpenID 2.0 messages.");
  }
 
  $server_url = $this->server->op_endpoint;
  }
 
  if ($allow) {
  $mode = 'id_res';
  } else if ($this->message->isOpenID1()) {
  if ($this->immediate) {
  $mode = 'id_res';
  } else {
  $mode = 'cancel';
  }
  } else {
  if ($this->immediate) {
  $mode = 'setup_needed';
  } else {
  $mode = 'cancel';
  }
  }
 
  if (!$this->trustRootValid()) {
  return new Auth_OpenID_UntrustedReturnURL(null,
  $this->return_to,
  $this->trust_root);
  }
 
  $response = new Auth_OpenID_ServerResponse($this);
 
  if ($claimed_id &&
  ($this->message->isOpenID1())) {
  return new Auth_OpenID_ServerError(null,
  "claimed_id is new in OpenID 2.0 and not " .
  "available for ".$this->namespace);
  }
 
  if ($identity && !$claimed_id) {
  $claimed_id = $identity;
  }
 
  if ($allow) {
 
  if ($this->identity == Auth_OpenID_IDENTIFIER_SELECT) {
  if (!$identity) {
  return new Auth_OpenID_ServerError(null,
  "This request uses IdP-driven identifier selection. " .
  "You must supply an identifier in the response.");
  }
 
  $response_identity = $identity;
  $response_claimed_id = $claimed_id;
 
  } else if ($this->identity) {
  if ($identity &&
  ($this->identity != $identity)) {
  $fmt = "Request was for %s, cannot reply with identity %s";
  return new Auth_OpenID_ServerError(null,
  sprintf($fmt, $this->identity, $identity));
  }
 
  $response_identity = $this->identity;
  $response_claimed_id = $this->claimed_id;
  } else {
  if ($identity) {
  return new Auth_OpenID_ServerError(null,
  "This request specified no identity and " .
  "you supplied ".$identity);
  }
 
  $response_identity = null;
  }
 
  if (($this->message->isOpenID1()) &&
  ($response_identity === null)) {
  return new Auth_OpenID_ServerError(null,
  "Request was an OpenID 1 request, so response must " .
  "include an identifier.");
  }
 
  $response->fields->updateArgs(Auth_OpenID_OPENID_NS,
  array('mode' => $mode,
  'return_to' => $this->return_to,
  'response_nonce' => Auth_OpenID_mkNonce()));
 
  if (!$this->message->isOpenID1()) {
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'op_endpoint', $server_url);
  }
 
  if ($response_identity !== null) {
  $response->fields->setArg(
  Auth_OpenID_OPENID_NS,
  'identity',
  $response_identity);
  if ($this->message->isOpenID2()) {
  $response->fields->setArg(
  Auth_OpenID_OPENID_NS,
  'claimed_id',
  $response_claimed_id);
  }
  }
 
  } else {
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'mode', $mode);
 
  if ($this->immediate) {
  if (($this->message->isOpenID1()) &&
  (!$server_url)) {
  return new Auth_OpenID_ServerError(null,
  'setup_url is required for $allow=false \
  in OpenID 1.x immediate mode.');
  }
 
  $setup_request = new Auth_OpenID_CheckIDRequest(
  $this->identity,
  $this->return_to,
  $this->trust_root,
  false,
  $this->assoc_handle,
  $this->server,
  $this->claimed_id);
  $setup_request->message = $this->message;
 
  $setup_url = $setup_request->encodeToURL($server_url);
 
  if ($setup_url === null) {
  return new Auth_OpenID_NoReturnToError();
  }
 
  $response->fields->setArg(Auth_OpenID_OPENID_NS,
  'user_setup_url',
  $setup_url);
  }
  }
 
  return $response;
  }
 
  function encodeToURL($server_url)
  {
  if (!$this->return_to) {
  return new Auth_OpenID_NoReturnToError();
  }
 
  // Imported from the alternate reality where these classes are
  // used in both the client and server code, so Requests are
  // Encodable too. That's right, code imported from alternate
  // realities all for the love of you, id_res/user_setup_url.
 
  $q = array('mode' => $this->mode,
  'identity' => $this->identity,
  'claimed_id' => $this->claimed_id,
  'return_to' => $this->return_to);
 
  if ($this->trust_root) {
  if ($this->message->isOpenID1()) {
  $q['trust_root'] = $this->trust_root;
  } else {
  $q['realm'] = $this->trust_root;
  }
  }
 
  if ($this->assoc_handle) {
  $q['assoc_handle'] = $this->assoc_handle;
  }
 
  $response = new Auth_OpenID_Message(
  $this->message->getOpenIDNamespace());
  $response->updateArgs(Auth_OpenID_OPENID_NS, $q);
  return $response->toURL($server_url);
  }
 
  function getCancelURL()
  {
  if (!$this->return_to) {
  return new Auth_OpenID_NoReturnToError();
  }
 
  if ($this->immediate) {
  return new Auth_OpenID_ServerError(null,
  "Cancel is not an appropriate \
  response to immediate mode \
  requests.");
  }
 
  $response = new Auth_OpenID_Message(
  $this->message->getOpenIDNamespace());
  $response->setArg(Auth_OpenID_OPENID_NS, 'mode', 'cancel');
  return $response->toURL($this->return_to);
  }
  }
 
  /**
  * This class encapsulates the response to an OpenID server request.
  *
  * @package OpenID
  */
  class Auth_OpenID_ServerResponse {
 
  function Auth_OpenID_ServerResponse($request)
  {
  $this->request = $request;
  $this->fields = new Auth_OpenID_Message($this->request->namespace);
  }
 
  function whichEncoding()
  {
  global $_Auth_OpenID_Request_Modes;
 
  if (in_array($this->request->mode, $_Auth_OpenID_Request_Modes)) {
  if ($this->fields->isOpenID2() &&
  (strlen($this->encodeToURL()) >
  Auth_OpenID_OPENID1_URL_LIMIT)) {
  return Auth_OpenID_ENCODE_HTML_FORM;
  } else {
  return Auth_OpenID_ENCODE_URL;
  }
  } else {
  return Auth_OpenID_ENCODE_KVFORM;
  }
  }
 
  /*
  * Returns the form markup for this response.
  *
  * @return str
  */
  function toFormMarkup($form_tag_attrs=null)
  {
  return $this->fields->toFormMarkup($this->request->return_to,
  $form_tag_attrs);
  }
 
  /*
  * Returns an HTML document containing the form markup for this
  * response that autosubmits with javascript.
  */
  function toHTML()
  {
  return Auth_OpenID::autoSubmitHTML($this->toFormMarkup());
  }
 
  /*
  * Returns True if this response's encoding is ENCODE_HTML_FORM.
  * Convenience method for server authors.
  *
  * @return bool
  */
  function renderAsForm()
  {
  return $this->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM;
  }
 
 
  function encodeToURL()
  {
  return $this->fields->toURL($this->request->return_to);
  }
 
  function addExtension($extension_response)
  {
  $extension_response->toMessage($this->fields);
  }
 
  function needsSigning()
  {
  return $this->fields->getArg(Auth_OpenID_OPENID_NS,
  'mode') == 'id_res';
  }
 
  function encodeToKVForm()
  {
  return $this->fields->toKVForm();
  }
  }
 
  /**
  * A web-capable response object which you can use to generate a
  * user-agent response.
  *
  * @package OpenID
  */
  class Auth_OpenID_WebResponse {
  var $code = AUTH_OPENID_HTTP_OK;
  var $body = "";
 
  function Auth_OpenID_WebResponse($code = null, $headers = null,
  $body = null)
  {
  if ($code) {
  $this->code = $code;
  }
 
  if ($headers !== null) {
  $this->headers = $headers;
  } else {
  $this->headers = array();
  }
 
  if ($body !== null) {
  $this->body = $body;
  }
  }
  }
 
  /**
  * Responsible for the signature of query data and the verification of
  * OpenID signature values.
  *
  * @package OpenID
  */
  class Auth_OpenID_Signatory {
 
  // = 14 * 24 * 60 * 60; # 14 days, in seconds
  var $SECRET_LIFETIME = 1209600;
 
  // keys have a bogus server URL in them because the filestore
  // really does expect that key to be a URL. This seems a little
  // silly for the server store, since I expect there to be only one
  // server URL.
  var $normal_key = 'http://localhost/|normal';
  var $dumb_key = 'http://localhost/|dumb';
 
  /**
  * Create a new signatory using a given store.
  */
  function Auth_OpenID_Signatory($store)
  {
  // assert store is not None
  $this->store = $store;
  }
 
  /**
  * Verify, using a given association handle, a signature with
  * signed key-value pairs from an HTTP request.
  */
  function verify($assoc_handle, $message)
  {
  $assoc = $this->getAssociation($assoc_handle, true);
  if (!$assoc) {
  // oidutil.log("failed to get assoc with handle %r to verify sig %r"
  // % (assoc_handle, sig))
  return false;
  }
 
  return $assoc->checkMessageSignature($message);
  }
 
  /**
  * Given a response, sign the fields in the response's 'signed'
  * list, and insert the signature into the response.
  */
  function sign($response)
  {
  $signed_response = $response;
  $assoc_handle = $response->request->assoc_handle;
 
  if ($assoc_handle) {
  // normal mode
  $assoc = $this->getAssociation($assoc_handle, false, false);
  if (!$assoc || ($assoc->getExpiresIn() <= 0)) {
  // fall back to dumb mode
  $signed_response->fields->setArg(Auth_OpenID_OPENID_NS,
  'invalidate_handle', $assoc_handle);
  $assoc_type = ($assoc ? $assoc->assoc_type : 'HMAC-SHA1');
 
  if ($assoc && ($assoc->getExpiresIn() <= 0)) {
  $this->invalidate($assoc_handle, false);
  }
 
  $assoc = $this->createAssociation(true, $assoc_type);
  }
  } else {
  // dumb mode.
  $assoc = $this->createAssociation(true);
  }
 
  $signed_response->fields = $assoc->signMessage(
  $signed_response->fields);
  return $signed_response;
  }
 
  /**
  * Make a new association.
  */
  function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1')
  {
  $secret = Auth_OpenID_CryptUtil::getBytes(
  Auth_OpenID_getSecretSize($assoc_type));
 
  $uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4));
  $handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq);
 
  $assoc = Auth_OpenID_Association::fromExpiresIn(
  $this->SECRET_LIFETIME, $handle, $secret, $assoc_type);
 
  if ($dumb) {
  $key = $this->dumb_key;
  } else {
  $key = $this->normal_key;
  }
 
  $this->store->storeAssociation($key, $assoc);
  return $assoc;
  }
 
  /**
  * Given an association handle, get the association from the
  * store, or return a ServerError or null if something goes wrong.
  */
  function getAssociation($assoc_handle, $dumb, $check_expiration=true)
  {
  if ($assoc_handle === null) {
  return new Auth_OpenID_ServerError(null,
  "assoc_handle must not be null");
  }
 
  if ($dumb) {
  $key = $this->dumb_key;
  } else {
  $key = $this->normal_key;
  }
 
  $assoc = $this->store->getAssociation($key, $assoc_handle);
 
  if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) {
  if ($check_expiration) {
  $this->store->removeAssociation($key, $assoc_handle);
  $assoc = null;
  }
  }
 
  return $assoc;
  }
 
  /**
  * Invalidate a given association handle.
  */
  function invalidate($assoc_handle, $dumb)
  {
  if ($dumb) {
  $key = $this->dumb_key;
  } else {
  $key = $this->normal_key;
  }
  $this->store->removeAssociation($key, $assoc_handle);
  }
  }
 
  /**
  * Encode an {@link Auth_OpenID_ServerResponse} to an
  * {@link Auth_OpenID_WebResponse}.
  *
  * @package OpenID
  */
  class Auth_OpenID_Encoder {
 
  var $responseFactory = 'Auth_OpenID_WebResponse';
 
  /**
  * Encode an {@link Auth_OpenID_ServerResponse} and return an
  * {@link Auth_OpenID_WebResponse}.
  */
  function encode($response)
  {
  $cls = $this->responseFactory;
 
  $encode_as = $response->whichEncoding();
  if ($encode_as == Auth_OpenID_ENCODE_KVFORM) {
  $wr = new $cls(null, null, $response->encodeToKVForm());
  if (is_a($response, 'Auth_OpenID_ServerError')) {
  $wr->code = AUTH_OPENID_HTTP_ERROR;
  }
  } else if ($encode_as == Auth_OpenID_ENCODE_URL) {
  $location = $response->encodeToURL();
  $wr = new $cls(AUTH_OPENID_HTTP_REDIRECT,
  array('location' => $location));
  } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) {
  $wr = new $cls(AUTH_OPENID_HTTP_OK, array(),
  $response->toHTML());
  } else {
  return new Auth_OpenID_EncodingError($response);
  }
  /* Allow the response to carry a custom error code (ex: for Association errors) */
  if(isset($response->code)) {
  $wr->code = $response->code;
  }
  return $wr;
  }
  }
 
  /**
  * An encoder which also takes care of signing fields when required.
  *
  * @package OpenID
  */
  class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder {
 
  function Auth_OpenID_SigningEncoder($signatory)
  {
  $this->signatory = $signatory;
  }
 
  /**
  * Sign an {@link Auth_OpenID_ServerResponse} and return an
  * {@link Auth_OpenID_WebResponse}.
  */
  function encode($response)
  {
  // the isinstance is a bit of a kludge... it means there isn't
  // really an adapter to make the interfaces quite match.
  if (!is_a($response, 'Auth_OpenID_ServerError') &&
  $response->needsSigning()) {
 
  if (!$this->signatory) {
  return new Auth_OpenID_ServerError(null,
  "Must have a store to sign request");
  }
 
  if ($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')) {
  return new Auth_OpenID_AlreadySigned($response);
  }
  $response = $this->signatory->sign($response);
  }
 
  return parent::encode($response);
  }
  }
 
  /**
  * Decode an incoming query into an Auth_OpenID_Request.
  *
  * @package OpenID
  */
  class Auth_OpenID_Decoder {
 
  function Auth_OpenID_Decoder($server)
  {
  $this->server = $server;
 
  $this->handlers = array(
  'checkid_setup' => 'Auth_OpenID_CheckIDRequest',
  'checkid_immediate' => 'Auth_OpenID_CheckIDRequest',
  'check_authentication' => 'Auth_OpenID_CheckAuthRequest',
  'associate' => 'Auth_OpenID_AssociateRequest'
  );
  }
 
  /**
  * Given an HTTP query in an array (key-value pairs), decode it
  * into an Auth_OpenID_Request object.
  */
  function decode($query)
  {
  if (!$query) {
  return null;
  }
 
  $message = Auth_OpenID_Message::fromPostArgs($query);
 
  if ($message === null) {
  /*
  * It's useful to have a Message attached to a
  * ProtocolError, so we override the bad ns value to build
  * a Message out of it. Kinda kludgy, since it's made of
  * lies, but the parts that aren't lies are more useful
  * than a 'None'.
  */
  $old_ns = $query['openid.ns'];
 
  $query['openid.ns'] = Auth_OpenID_OPENID2_NS;
  $message = Auth_OpenID_Message::fromPostArgs($query);
  return new Auth_OpenID_ServerError(
  $message,
  sprintf("Invalid OpenID namespace URI: %s", $old_ns));
  }
 
  $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
  if (!$mode) {
  return new Auth_OpenID_ServerError($message,
  "No mode value in message");
  }
 
  if (Auth_OpenID::isFailure($mode)) {
  return new Auth_OpenID_ServerError($message,
  $mode->message);
  }
 
  $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode,
  $this->defaultDecoder($message));
 
  if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) {
  return call_user_func_array(array($handlerCls, 'fromMessage'),
  array($message, $this->server));
  } else {
  return $handlerCls;
  }
  }
 
  function defaultDecoder($message)
  {
  $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode');
 
  if (Auth_OpenID::isFailure($mode)) {
  return new Auth_OpenID_ServerError($message,
  $mode->message);
  }
 
  return new Auth_OpenID_ServerError($message,
  sprintf("Unrecognized OpenID mode %s", $mode));
  }
  }
 
  /**
  * An error that indicates an encoding problem occurred.
  *
  * @package OpenID
  */
  class Auth_OpenID_EncodingError {
  function Auth_OpenID_EncodingError($response)
  {
  $this->response = $response;
  }
  }
 
  /**
  * An error that indicates that a response was already signed.
  *
  * @package OpenID
  */
  class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError {
  // This response is already signed.
  }
 
  /**
  * An error that indicates that the given return_to is not under the
  * given trust_root.
  *
  * @package OpenID
  */
  class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError {
  function Auth_OpenID_UntrustedReturnURL($message, $return_to,
  $trust_root)
  {
  parent::Auth_OpenID_ServerError($message, "Untrusted return_to URL");
  $this->return_to = $return_to;
  $this->trust_root = $trust_root;
  }
 
  function toString()
  {
  return sprintf("return_to %s not under trust_root %s",
  $this->return_to, $this->trust_root);
  }
  }
 
  /**
  * I handle requests for an OpenID server.
  *
  * Some types of requests (those which are not checkid requests) may
  * be handed to my {@link handleRequest} method, and I will take care
  * of it and return a response.
  *
  * For your convenience, I also provide an interface to {@link
  * Auth_OpenID_Decoder::decode()} and {@link
  * Auth_OpenID_SigningEncoder::encode()} through my methods {@link
  * decodeRequest} and {@link encodeResponse}.
  *
  * All my state is encapsulated in an {@link Auth_OpenID_OpenIDStore}.
  *
  * Example:
  *
  * <pre> $oserver = new Auth_OpenID_Server(Auth_OpenID_FileStore($data_path),
  * "http://example.com/op");
  * $request = $oserver->decodeRequest();
  * if (in_array($request->mode, array('checkid_immediate',
  * 'checkid_setup'))) {
  * if ($app->isAuthorized($request->identity, $request->trust_root)) {
  * $response = $request->answer(true);
  * } else if ($request->immediate) {
  * $response = $request->answer(false);
  * } else {
  * $app->showDecidePage($request);
  * return;
  * }
  * } else {
  * $response = $oserver->handleRequest($request);
  * }
  *
  * $webresponse = $oserver->encode($response);</pre>
  *
  * @package OpenID
  */
  class Auth_OpenID_Server {
  function Auth_OpenID_Server($store, $op_endpoint=null)
  {
  $this->store = $store;
  $this->signatory = new Auth_OpenID_Signatory($this->store);
  $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory);
  $this->decoder = new Auth_OpenID_Decoder($this);
  $this->op_endpoint = $op_endpoint;
  $this->negotiator = Auth_OpenID_getDefaultNegotiator();
  }
 
  /**
  * Handle a request. Given an {@link Auth_OpenID_Request} object,
  * call the appropriate {@link Auth_OpenID_Server} method to
  * process the request and generate a response.
  *
  * @param Auth_OpenID_Request $request An {@link Auth_OpenID_Request}
  * returned by {@link Auth_OpenID_Server::decodeRequest()}.
  *
  * @return Auth_OpenID_ServerResponse $response A response object
  * capable of generating a user-agent reply.
  */
  function handleRequest($request)
  {
  if (method_exists($this, "openid_" . $request->mode)) {
  $handler = array($this, "openid_" . $request->mode);
  return call_user_func($handler, $request);
  }
  return null;
  }
 
  /**
  * The callback for 'check_authentication' messages.
  */
  function openid_check_authentication($request)
  {
  return $request->answer($this->signatory);
  }
 
  /**
  * The callback for 'associate' messages.
  */
  function openid_associate($request)
  {
  $assoc_type = $request->assoc_type;
  $session_type = $request->session->session_type;
  if ($this->negotiator->isAllowed($assoc_type, $session_type)) {
  $assoc = $this->signatory->createAssociation(false,
  $assoc_type);
  return $request->answer($assoc);
  } else {
  $message = sprintf('Association type %s is not supported with '.
  'session type %s', $assoc_type, $session_type);
  list($preferred_assoc_type, $preferred_session_type) =
  $this->negotiator->getAllowedType();
  return $request->answerUnsupported($message,
  $preferred_assoc_type,
  $preferred_session_type);
  }
  }
 
  /**
  * Encodes as response in the appropriate format suitable for
  * sending to the user agent.
  */
  function encodeResponse($response)
  {
  return $this->encoder->encode($response);
  }
 
  /**
  * Decodes a query args array into the appropriate
  * {@link Auth_OpenID_Request} object.
  */
  function decodeRequest($query=null)
  {
  if ($query === null) {
  $query = Auth_OpenID::getQuery();
  }
 
  return $this->decoder->decode($query);
  }
  }
 
 
 
  <?php
  /**
  * Functions for dealing with OpenID trust roots
  *
  * PHP versions 4 and 5
  *
  * LICENSE: See the COPYING file included in this distribution.
  *
  * @package OpenID
  * @author JanRain, Inc. <openid@janrain.com>
  * @copyright 2005-2008 Janrain, Inc.
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  */
 
  require_once 'Auth/OpenID/Discover.php';
 
  /**
  * A regular expression that matches a domain ending in a top-level domains.
  * Used in checking trust roots for sanity.
  *
  * @access private
  */
  define('Auth_OpenID___TLDs',
  '/\.(ac|ad|ae|aero|af|ag|ai|al|am|an|ao|aq|ar|arpa|as|asia' .
  '|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|biz|bj|bm|bn|bo|br' .
  '|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co' .
  '|com|coop|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg' .
  '|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl' .
  '|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie' .
  '|il|im|in|info|int|io|iq|ir|is|it|je|jm|jo|jobs|jp|ke|kg|kh' .
  '|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly' .
  '|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mo|mobi|mp|mq|mr|ms|mt' .
  '|mu|museum|mv|mw|mx|my|mz|na|name|nc|ne|net|nf|ng|ni|nl|no' .
  '|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pro|ps|pt' .
  '|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl' .
  '|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm' .
  '|tn|to|tp|tr|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve' .
  '|vg|vi|vn|vu|wf|ws|xn--0zwm56d|xn--11b5bs3a9aj6g' .
  '|xn--80akhbyknj4f|xn--9t4b11yi5a|xn--deba0ad|xn--g6w251d' .
  '|xn--hgbk6aj7f53bba|xn--hlcj6aya9esc7a|xn--jxalpdlp' .
  '|xn--kgbechtv|xn--zckzah|ye|yt|yu|za|zm|zw)\.?$/');
 
  define('Auth_OpenID___HostSegmentRe',
  "/^(?:[-a-zA-Z0-9!$&'\\(\\)\\*+,;=._~]|%[a-zA-Z0-9]{2})*$/");
 
  /**
  * A wrapper for trust-root related functions
  */
  class Auth_OpenID_TrustRoot {
  /*
  * Return a discovery URL for this realm.
  *
  * Return null if the realm could not be parsed or was not valid.
  *
  * @param return_to The relying party return URL of the OpenID
  * authentication request
  *
  * @return The URL upon which relying party discovery should be
  * run in order to verify the return_to URL
  */
  static function buildDiscoveryURL($realm)
  {
  $parsed = Auth_OpenID_TrustRoot::_parse($realm);
 
  if ($parsed === false) {
  return false;
  }
 
  if ($parsed['wildcard']) {
  // Use "www." in place of the star
  if ($parsed['host'][0] != '.') {
  return false;
  }
 
  $www_domain = 'www' . $parsed['host'];
 
  return sprintf('%s://%s%s', $parsed['scheme'],
  $www_domain, $parsed['path']);
  } else {
  return $parsed['unparsed'];
  }
  }
 
  /**
  * Parse a URL into its trust_root parts.
  *
  * @static
  *
  * @access private
  *
  * @param string $trust_root The url to parse
  *
  * @return mixed $parsed Either an associative array of trust root
  * parts or false if parsing failed.
  */
  static function _parse($trust_root)
  {
  $trust_root = Auth_OpenID_urinorm($trust_root);
  if ($trust_root === null) {
  return false;
  }
 
  if (preg_match("/:\/\/[^:]+(:\d+){2,}(\/|$)/", $trust_root)) {
  return false;
  }
 
  $parts = @parse_url($trust_root);
  if ($parts === false) {
  return false;
  }
 
  $required_parts = array('scheme', 'host');
  $forbidden_parts = array('user', 'pass', 'fragment');
  $keys = array_keys($parts);
  if (array_intersect($keys, $required_parts) != $required_parts) {
  return false;
  }
 
  if (array_intersect($keys, $forbidden_parts) != array()) {
  return false;
  }
 
  if (!preg_match(Auth_OpenID___HostSegmentRe, $parts['host'])) {
  return false;
  }
 
  $scheme = strtolower($parts['scheme']);
  $allowed_schemes = array('http', 'https');
  if (!in_array($scheme, $allowed_schemes)) {
  return false;
  }
  $parts['scheme'] = $scheme;
 
  $host = strtolower($parts['host']);
  $hostparts = explode('*', $host);
  switch (count($hostparts)) {
  case 1:
  $parts['wildcard'] = false;
  break;
  case 2:
  if ($hostparts[0] ||
  ($hostparts[1] && substr($hostparts[1], 0, 1) != '.')) {
  return false;
  }
  $host = $hostparts[1];
  $parts['wildcard'] = true;
  break;
  default:
  return false;
  }
  if (strpos($host, ':') !== false) {
  return false;
  }
 
  $parts['host'] = $host;
 
  if (isset($parts['path'])) {
  $path = strtolower($parts['path']);
  if (substr($path, 0, 1) != '/') {
  return false;
  }
  } else {
  $path = '/';
  }
 
  $parts['path'] = $path;
  if (!isset($parts['port'])) {
  $parts['port'] = false;
  }
 
 
  $parts['unparsed'] = $trust_root;
 
  return $parts;
  }
 
  /**
  * Is this trust root sane?
  *
  * A trust root is sane if it is syntactically valid and it has a
  * reasonable domain name. Specifically, the domain name must be
  * more than one level below a standard TLD or more than two
  * levels below a two-letter tld.
  *
  * For example, '*.com' is not a sane trust root, but '*.foo.com'
  * is. '*.co.uk' is not sane, but '*.bbc.co.uk' is.
  *
  * This check is not always correct, but it attempts to err on the
  * side of marking sane trust roots insane instead of marking
  * insane trust roots sane. For example, 'kink.fm' is marked as
  * insane even though it "should" (for some meaning of should) be
  * marked sane.
  *
  * This function should be used when creating OpenID servers to
  * alert the users of the server when a consumer attempts to get
  * the user to accept a suspicious trust root.
  *
  * @static
  * @param string $trust_root The trust root to check
  * @return bool $sanity Whether the trust root looks OK
  */
  static function isSane($trust_root)
  {
  $parts = Auth_OpenID_TrustRoot::_parse($trust_root);
  if ($parts === false) {
  return false;
  }
 
  // Localhost is a special case
  if ($parts['host'] == 'localhost') {
  return true;
  }
 
  $host_parts = explode('.', $parts['host']);
  if ($parts['wildcard']) {
  // Remove the empty string from the beginning of the array
  array_shift($host_parts);
  }
 
  if ($host_parts && !$host_parts[count($host_parts) - 1]) {
  array_pop($host_parts);
  }
 
  if (!$host_parts) {
  return false;
  }
 
  // Don't allow adjacent dots
  if (in_array('', $host_parts, true)) {
  return false;
  }
 
  // Get the top-level domain of the host. If it is not a valid TLD,
  // it's not sane.
  preg_match(Auth_OpenID___TLDs, $parts['host'], $matches);
  if (!$matches) {
  return false;
  }
  $tld = $matches[1];
 
  if (count($host_parts) == 1) {
  return false;
  }
 
  if ($parts['wildcard']) {
  // It's a 2-letter tld with a short second to last segment
  // so there needs to be more than two segments specified
  // (e.g. *.co.uk is insane)
  $second_level = $host_parts[count($host_parts) - 2];
  if (strlen($tld) == 2 && strlen($second_level) <= 3) {
  return count($host_parts) > 2;
  }
  }
 
  return true;
  }
 
  /**
  * Does this URL match the given trust root?
  *
  * Return whether the URL falls under the given trust root. This
  * does not check whether the trust root is sane. If the URL or
  * trust root do not parse, this function will return false.
  *
  * @param string $trust_root The trust root to match against
  *
  * @param string $url The URL to check
  *
  * @return bool $matches Whether the URL matches against the
  * trust root
  */
  static function match($trust_root, $url)
  {
  $trust_root_parsed = Auth_OpenID_TrustRoot::_parse($trust_root);
  $url_parsed = Auth_OpenID_TrustRoot::_parse($url);
  if (!$trust_root_parsed || !$url_parsed) {
  return false;
  }
 
  // Check hosts matching
  if ($url_parsed['wildcard']) {
  return false;
  }
  if ($trust_root_parsed['wildcard']) {
  $host_tail = $trust_root_parsed['host'];
  $host = $url_parsed['host'];
  if ($host_tail &&
  substr($host, -(strlen($host_tail))) != $host_tail &&
  substr($host_tail, 1) != $host) {
  return false;
  }
  } else {
  if ($trust_root_parsed['host'] != $url_parsed['host']) {
  return false;
  }
  }
 
  // Check path and query matching
  $base_path = $trust_root_parsed['path'];
  $path = $url_parsed['path'];
  if (!isset($trust_root_parsed['query'])) {
  if ($base_path != $path) {
  if (substr($path, 0, strlen($base_path)) != $base_path) {
  return false;
  }
  if (substr($base_path, strlen($base_path) - 1, 1) != '/' &&
  substr($path, strlen($base_path), 1) != '/') {
  return false;
  }
  }
  } else {
  $base_query = $trust_root_parsed['query'];
  $query = @$url_parsed['query'];
  $qplus = substr($query, 0, strlen($base_query) + 1);
  $bqplus = $base_query . '&';
  if ($base_path != $path ||
  ($base_query != $query && $qplus != $bqplus)) {
  return false;
  }
  }
 
  // The port and scheme need to match exactly
  return ($trust_root_parsed['scheme'] == $url_parsed['scheme'] &&
  $url_parsed['port'] === $trust_root_parsed['port']);
  }
  }
 
  /*
  * If the endpoint is a relying party OpenID return_to endpoint,
  * return the endpoint URL. Otherwise, return None.
  *
  * This function is intended to be used as a filter for the Yadis
  * filtering interface.
  *
  * @see: C{L{openid.yadis.services}}
  * @see: C{L{openid.yadis.filters}}
  *
  * @param endpoint: An XRDS BasicServiceEndpoint, as returned by
  * performing Yadis dicovery.
  *
  * @returns: The endpoint URL or None if the endpoint is not a
  * relying party endpoint.
  */
  function filter_extractReturnURL($endpoint)
  {
  if ($endpoint->matchTypes(array(Auth_OpenID_RP_RETURN_TO_URL_TYPE))) {
  return $endpoint;
  } else {
  return null;
  }
  }
 
  function &Auth_OpenID_extractReturnURL(&$endpoint_list)
  {
  $result = array();
 
  foreach ($endpoint_list as $endpoint) {
  if (filter_extractReturnURL($endpoint)) {
  $result[] = $endpoint;
  }
  }
 
  return $result;
  }
 
  /*
  * Is the return_to URL under one of the supplied allowed return_to
  * URLs?
  */
  function Auth_OpenID_returnToMatches($allowed_return_to_urls, $return_to)
  {
  foreach ($allowed_return_to_urls as $allowed_return_to) {
  // A return_to pattern works the same as a realm, except that
  // it's not allowed to use a wildcard. We'll model this by
  // parsing it as a realm, and not trying to match it if it has
  // a wildcard.
 
  $return_realm = Auth_OpenID_TrustRoot::_parse($allowed_return_to);
  if (// Parses as a trust root
  ($return_realm !== false) &&
  // Does not have a wildcard
  (!$return_realm['wildcard']) &&
  // Matches the return_to that we passed in with it
  (Auth_OpenID_TrustRoot::match($allowed_return_to, $return_to))) {
  return true;
  }
  }
 
  // No URL in the list matched
  return false;
  }
 
  /*
  * Given a relying party discovery URL return a list of return_to
  * URLs.
  */
  function Auth_OpenID_getAllowedReturnURLs($relying_party_url, $fetcher,
  $discover_function=null)
  {
  if ($discover_function === null) {
  $discover_function = array('Auth_Yadis_Yadis', 'discover');
  }
 
  $xrds_parse_cb = array('Auth_OpenID_ServiceEndpoint', 'consumerFromXRDS');
 
  list($rp_url_after_redirects, $endpoints) =
  Auth_Yadis_getServiceEndpoints($relying_party_url, $xrds_parse_cb,
  $discover_function, $fetcher);
 
  if ($rp_url_after_redirects != $relying_party_url) {
  // Verification caused a redirect
  return false;
  }
 
  call_user_func_array($discover_function,
  array($relying_party_url, $fetcher));
 
  $return_to_urls = array();
  $matching_endpoints = Auth_OpenID_extractReturnURL($endpoints);
 
  foreach ($matching_endpoints as $e) {
  $return_to_urls[] = $e->server_url;
  }
 
  return $return_to_urls;
  }
 
  /*
  * Verify that a return_to URL is valid for the given realm.
  *
  * This function builds a discovery URL, performs Yadis discovery on
  * it, makes sure that the URL does not redirect, parses out the
  * return_to URLs, and finally checks to see if the current return_to
  * URL matches the return_to.
  *
  * @return true if the return_to URL is valid for the realm
  */
  function Auth_OpenID_verifyReturnTo($realm_str, $return_to, $fetcher,
  $_vrfy='Auth_OpenID_getAllowedReturnURLs')
  {
  $disco_url = Auth_OpenID_TrustRoot::buildDiscoveryURL($realm_str);
 
  if ($disco_url === false) {
  return false;
  }
 
  $allowable_urls = call_user_func_array($_vrfy,
  array($disco_url, $fetcher));
 
  // The realm_str could not be parsed.
  if ($allowable_urls === false) {
  return false;
  }
 
  if (Auth_OpenID_returnToMatches($allowable_urls, $return_to)) {
  return true;
  } else {
  return false;
  }
  }
 
 
  <?php
 
  /**
  * Yadis service manager to be used during yadis-driven authentication
  * attempts.
  *
  * @package OpenID
  */
 
  /**
  * The base session class used by the Auth_Yadis_Manager. This
  * class wraps the default PHP session machinery and should be
  * subclassed if your application doesn't use PHP sessioning.
  *
  * @package OpenID
  */
  class Auth_Yadis_PHPSession {
  /**
  * Set a session key/value pair.
  *
  * @param string $name The name of the session key to add.
  * @param string $value The value to add to the session.
  */
  function set($name, $value)
  {
  $_SESSION[$name] = $value;
  }
 
  /**
  * Get a key's value from the session.
  *
  * @param string $name The name of the key to retrieve.
  * @param string $default The optional value to return if the key
  * is not found in the session.
  * @return string $result The key's value in the session or
  * $default if it isn't found.
  */
  function get($name, $default=null)
  {
  if (array_key_exists($name, $_SESSION)) {
  return $_SESSION[$name];
  } else {
  return $default;
  }
  }
 
  /**
  * Remove a key/value pair from the session.
  *
  * @param string $name The name of the key to remove.
  */
  function del($name)
  {
  unset($_SESSION[$name]);
  }
 
  /**
  * Return the contents of the session in array form.
  */
  function contents()
  {
  return $_SESSION;
  }
  }
 
  /**
  * A session helper class designed to translate between arrays and
  * objects. Note that the class used must have a constructor that
  * takes no parameters. This is not a general solution, but it works
  * for dumb objects that just need to have attributes set. The idea
  * is that you'll subclass this and override $this->check($data) ->
  * bool to implement your own session data validation.
  *
  * @package OpenID
  */
  class Auth_Yadis_SessionLoader {
  /**
  * Override this.
  *
  * @access private
  */
  function check($data)
  {
  return true;
  }
 
  /**
  * Given a session data value (an array), this creates an object
  * (returned by $this->newObject()) whose attributes and values
  * are those in $data. Returns null if $data lacks keys found in
  * $this->requiredKeys(). Returns null if $this->check($data)
  * evaluates to false. Returns null if $this->newObject()
  * evaluates to false.
  *
  * @access private
  */
  function fromSession($data)
  {
  if (!$data) {
  return null;
  }
 
  $required = $this->requiredKeys();
 
  foreach ($required as $k) {
  if (!array_key_exists($k, $data)) {
  return null;
  }
  }
 
  if (!$this->check($data)) {
  return null;
  }
 
  $data = array_merge($data, $this->prepareForLoad($data));
  $obj = $this->newObject($data);
 
  if (!$obj) {
  return null;
  }
 
  foreach ($required as $k) {
  $obj->$k = $data[$k];
  }
 
  return $obj;
  }
 
  /**
  * Prepares the data array by making any necessary changes.
  * Returns an array whose keys and values will be used to update
  * the original data array before calling $this->newObject($data).
  *
  * @access private
  */
  function prepareForLoad($data)
  {
  return array();
  }
 
  /**
  * Returns a new instance of this loader's class, using the
  * session data to construct it if necessary. The object need
  * only be created; $this->fromSession() will take care of setting
  * the object's attributes.
  *
  * @access private
  */
  function newObject($data)
  {
  return null;
  }
 
  /**
  * Returns an array of keys and values built from the attributes
  * of $obj. If $this->prepareForSave($obj) returns an array, its keys
  * and values are used to update the $data array of attributes
  * from $obj.
  *
  * @access private
  */
  function toSession($obj)
  {
  $data = array();
  foreach ($obj as $k => $v) {
  $data[$k] = $v;
  }
 
  $extra = $this->prepareForSave($obj);
 
  if ($extra && is_array($extra)) {
  foreach ($extra as $k => $v) {
  $data[$k] = $v;
  }
  }
 
  return $data;
  }
 
  /**
  * Override this.
  *
  * @access private
  */
  function prepareForSave($obj)
  {
  return array();
  }
  }
 
  /**
  * A concrete loader implementation for Auth_OpenID_ServiceEndpoints.
  *
  * @package OpenID
  */
  class Auth_OpenID_ServiceEndpointLoader extends Auth_Yadis_SessionLoader {
  function newObject($data)
  {
  return new Auth_OpenID_ServiceEndpoint();
  }
 
  function requiredKeys()
  {
  $obj = new Auth_OpenID_ServiceEndpoint();
  $data = array();
  foreach ($obj as $k => $v) {
  $data[] = $k;
  }
  return $data;
  }
 
  function check($data)
  {
  return is_array($data['type_uris']);
  }
  }
 
  /**
  * A concrete loader implementation for Auth_Yadis_Managers.
  *
  * @package OpenID
  */
  class Auth_Yadis_ManagerLoader extends Auth_Yadis_SessionLoader {
  function requiredKeys()
  {
  return array('starting_url',
  'yadis_url',
  'services',
  'session_key',
  '_current',
  'stale');
  }
 
  function newObject($data)
  {
  return new Auth_Yadis_Manager($data['starting_url'],
  $data['yadis_url'],
  $data['services'],
  $data['session_key']);
  }
 
  function check($data)
  {
  return is_array($data['services']);
  }
 
  function prepareForLoad($data)
  {
  $loader = new Auth_OpenID_ServiceEndpointLoader();
  $services = array();
  foreach ($data['services'] as $s) {
  $services[] = $loader->fromSession($s);
  }
  return array('services' => $services);
  }
 
  function prepareForSave($obj)
  {
  $loader = new Auth_OpenID_ServiceEndpointLoader();
  $services = array();
  foreach ($obj->services as $s) {
  $services[] = $loader->toSession($s);
  }
  return array('services' => $services);
  }
  }
 
  /**
  * The Yadis service manager which stores state in a session and
  * iterates over <Service> elements in a Yadis XRDS document and lets
  * a caller attempt to use each one. This is used by the Yadis
  * library internally.
  *
  * @package OpenID
  */
  class Auth_Yadis_Manager {
 
  /**
  * Intialize a new yadis service manager.
  *
  * @access private
  */
  function Auth_Yadis_Manager($starting_url, $yadis_url,
  $services, $session_key)
  {
  // The URL that was used to initiate the Yadis protocol
  $this->starting_url = $starting_url;
 
  // The URL after following redirects (the identifier)
  $this->yadis_url = $yadis_url;
 
  // List of service elements
  $this->services = $services;
 
  $this->session_key = $session_key;
 
  // Reference to the current service object
  $this->_current = null;
 
  // Stale flag for cleanup if PHP lib has trouble.
  $this->stale = false;
  }
 
  /**
  * @access private
  */
  function length()
  {
  // How many untried services remain?
  return count($this->services);
  }
 
  /**
  * Return the next service
  *
  * $this->current() will continue to return that service until the
  * next call to this method.
  */
  function nextService()
  {
 
  if ($this->services) {
  $this->_current = array_shift($this->services);
  } else {
  $this->_current = null;
  }
 
  return $this->_current;
  }
 
  /**
  * @access private
  */
  function current()
  {
  // Return the current service.
  // Returns None if there are no services left.
  return $this->_current;
  }
 
  /**
  * @access private
  */
  function forURL($url)
  {
  return in_array($url, array($this->starting_url, $this->yadis_url));
  }
 
  /**
  * @access private
  */
  function started()
  {
  // Has the first service been returned?
  return $this->_current !== null;
  }
  }
 
  /**
  * State management for discovery.
  *
  * High-level usage pattern is to call .getNextService(discover) in
  * order to find the next available service for this user for this
  * session. Once a request completes, call .cleanup() to clean up the
  * session state.
  *
  * @package OpenID
  */
  class Auth_Yadis_Discovery {
 
  /**
  * @access private
  */
  var $DEFAULT_SUFFIX = 'auth';
 
  /**
  * @access private
  */
  var $PREFIX = '_yadis_services_';
 
  /**
  * Initialize a discovery object.
  *
  * @param Auth_Yadis_PHPSession $session An object which
  * implements the Auth_Yadis_PHPSession API.
  * @param string $url The URL on which to attempt discovery.
  * @param string $session_key_suffix The optional session key
  * suffix override.
  */
  function Auth_Yadis_Discovery($session, $url,
  $session_key_suffix = null)
  {
  /// Initialize a discovery object
  $this->session = $session;
  $this->url = $url;
  if ($session_key_suffix === null) {
  $session_key_suffix = $this->DEFAULT_SUFFIX;
  }
 
  $this->session_key_suffix = $session_key_suffix;
  $this->session_key = $this->PREFIX . $this->session_key_suffix;
  }
 
  /**
  * Return the next authentication service for the pair of
  * user_input and session. This function handles fallback.
  */
  function getNextService($discover_cb, $fetcher)
  {
  $manager = $this->getManager();
  if (!$manager || (!$manager->services)) {
  $this->destroyManager();
 
  list($yadis_url, $services) = call_user_func($discover_cb,
  $this->url,
  $fetcher);
 
  $manager = $this->createManager($services, $yadis_url);
  }
 
  if ($manager) {
  $loader = new Auth_Yadis_ManagerLoader();
  $service = $manager->nextService();
  $this->session->set($this->session_key,
  serialize($loader->toSession($manager)));
  } else {
  $service = null;
  }
 
  return $service;
  }
 
  /**
  * Clean up Yadis-related services in the session and return the
  * most-recently-attempted service from the manager, if one
  * exists.
  *
  * @param $force True if the manager should be deleted regardless
  * of whether it's a manager for $this->url.
  */
  function cleanup($force=false)
  {
  $manager = $this->getManager($force);
  if ($manager) {
  $service = $manager->current();
  $this->destroyManager($force);
  } else {
  $service = null;
  }
 
  return $service;
  }
 
  /**
  * @access private
  */
  function getSessionKey()
  {
  // Get the session key for this starting URL and suffix
  return $this->PREFIX . $this->session_key_suffix;
  }
 
  /**
  * @access private
  *
  * @param $force True if the manager should be returned regardless
  * of whether it's a manager for $this->url.
  */
  function getManager($force=false)
  {
  // Extract the YadisServiceManager for this object's URL and
  // suffix from the session.
 
  $manager_str = $this->session->get($this->getSessionKey());
  $manager = null;
 
  if ($manager_str !== null) {
  $loader = new Auth_Yadis_ManagerLoader();
  $manager = $loader->fromSession(unserialize($manager_str));
  }
 
  if ($manager && ($manager->forURL($this->url) || $force)) {
  return $manager;
  }
  }
 
  /**
  * @access private
  */
  function createManager($services, $yadis_url = null)
  {
  $key = $this->getSessionKey();
  if ($this->getManager()) {
  return $this->getManager();
  }
 
  if ($services) {
  $loader = new Auth_Yadis_ManagerLoader();
  $manager = new Auth_Yadis_Manager($this->url, $yadis_url,
  $services, $key);
  $this->session->set($this->session_key,
  serialize($loader->toSession($manager)));
  return $manager;
  }
  }
 
  /**
  * @access private
  *
  * @param $force True if the manager should be deleted regardless
  * of whether it's a manager for $this->url.
  */
  function destroyManager($force=false)
  {
  if ($this->getManager($force) !== null) {
  $key = $this->getSessionKey();
  $this->session->del($key);
  }
  }
  }
 
 
  <?php
 
  /**
  * This module contains the XRDS parsing code.
  *
  * PHP versions 4 and 5
  *
  * LICENSE: See the COPYING file included in this distribution.
  *
  * @package OpenID
  * @author JanRain, Inc. <openid@janrain.com>
  * @copyright 2005-2008 Janrain, Inc.
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
  */
 
  /**
  * Require the XPath implementation.
  */
  require_once 'Auth/Yadis/XML.php';
 
  /**
  * This match mode means a given service must match ALL filters passed
  * to the Auth_Yadis_XRDS::services() call.
  */
  define('SERVICES_YADIS_MATCH_ALL', 101);
 
  /**
  * This match mode means a given service must match ANY filters (at
  * least one) passed to the Auth_Yadis_XRDS::services() call.
  */
  define('SERVICES_YADIS_MATCH_ANY', 102);
 
  /**
  * The priority value used for service elements with no priority
  * specified.
  */
  define('SERVICES_YADIS_MAX_PRIORITY', pow(2, 30));
 
  /**
  * XRD XML namespace
  */
  define('Auth_Yadis_XMLNS_XRD_2_0', 'xri://$xrd*($v*2.0)');
 
  /**
  * XRDS XML namespace
  */
  define('Auth_Yadis_XMLNS_XRDS', 'xri://$xrds');
 
  function Auth_Yadis_getNSMap()
  {
  return array('xrds' => Auth_Yadis_XMLNS_XRDS,
  'xrd' => Auth_Yadis_XMLNS_XRD_2_0);
  }
 
  /**
  * @access private
  */
  function Auth_Yadis_array_scramble($arr)
  {
  $result = array();
 
  while (count($arr)) {
  $index = array_rand($arr, 1);
  $result[] = $arr[$index];
  unset($arr[$index]);
  }
 
  return $result;
  }
 
  /**
  * This class represents a <Service> element in an XRDS document.
  * Objects of this type are returned by
  * Auth_Yadis_XRDS::services() and
  * Auth_Yadis_Yadis::services(). Each object corresponds directly
  * to a <Service> element in the XRDS and supplies a
  * getElements($name) method which you should use to inspect the
  * element's contents. See {@link Auth_Yadis_Yadis} for more
  * information on the role this class plays in Yadis discovery.
  *
  * @package OpenID
  */
  class Auth_Yadis_Service {
 
  /**
  * Creates an empty service object.
  */
  function Auth_Yadis_Service()
  {
  $this->element = null;
  $this->parser = null;
  }
 
  /**
  * Return the URIs in the "Type" elements, if any, of this Service
  * element.
  *
  * @return array $type_uris An array of Type URI strings.
  */
  function getTypes()
  {
  $t = array();
  foreach ($this->getElements('xrd:Type') as $elem) {
  $c = $this->parser->content($elem);
  if ($c) {
  $t[] = $c;
  }
  }
  return $t;
  }
 
  function matchTypes($type_uris)
  {
  $result = array();
 
  foreach ($this->getTypes() as $typ) {
  if (in_array($typ, $type_uris)) {
  $result[] = $typ;
  }
  }
 
  return $result;
  }
 
  /**
  * Return the URIs in the "URI" elements, if any, of this Service
  * element. The URIs are returned sorted in priority order.
  *
  * @return array $uris An array of URI strings.
  */
  function getURIs()
  {
  $uris = array();
  $last = array();
 
  foreach ($this->getElements('xrd:URI') as $elem) {
  $uri_string = $this->parser->content($elem);
  $attrs = $this->parser->attributes($elem);
  if ($attrs &&
  array_key_exists('priority', $attrs)) {
  $priority = intval($attrs['priority']);
  if (!array_key_exists($priority, $uris)) {
  $uris[$priority] = array();
  }
 
  $uris[$priority][] = $uri_string;
  } else {
  $last[] = $uri_string;
  }
  }
 
  $keys = array_keys($uris);
  sort($keys);
 
  // Rebuild array of URIs.
  $result = array();
  foreach ($keys as $k) {
  $new_uris = Auth_Yadis_array_scramble($uris[$k]);
  $result = array_merge($result, $new_uris);
  }
 
  $result = array_merge($result,
  Auth_Yadis_array_scramble($last));
 
  return $result;
  }
 
  /**
  * Returns the "priority" attribute value of this <Service>
  * element, if the attribute is present. Returns null if not.
  *
  * @return mixed $result Null or integer, depending on whether
  * this Service element has a 'priority' attribute.
  */
  function getPriority()
  {
  $attributes = $this->parser->attributes($this->element);
 
  if (array_key_exists('priority', $attributes)) {
  return intval($attributes['priority']);
  }
 
  return null;
  }
 
  /**
  * Used to get XML elements from this object's <Service> element.
  *
  * This is what you should use to get all custom information out
  * of this element. This is used by service filter functions to
  * determine whether a service element contains specific tags,
  * etc. NOTE: this only considers elements which are direct
  * children of the <Service> element for this object.
  *
  * @param string $name The name of the element to look for
  * @return array $list An array of elements with the specified
  * name which are direct children of the <Service> element. The
  * nodes returned by this function can be passed to $this->parser
  * methods (see {@link Auth_Yadis_XMLParser}).
  */
  function getElements($name)
  {
  return $this->parser->evalXPath($name, $this->element);
  }
  }
 
  /*
  * Return the expiration date of this XRD element, or None if no
  * expiration was specified.
  *
  * @param $default The value to use as the expiration if no expiration
  * was specified in the XRD.
  */
  function Auth_Yadis_getXRDExpiration($xrd_element, $default=null)
  {
  $expires_element = $xrd_element->$parser->evalXPath('/xrd:Expires');
  if ($expires_element === null) {
  return $default;
  } else {
  $expires_string = $expires_element->text;
 
  // Will raise ValueError if the string is not the expected
  // format
  $t = strptime($expires_string, "%Y-%m-%dT%H:%M:%SZ");
 
  if ($t === false) {
  return false;
  }
 
  // [int $hour [, int $minute [, int $second [,
  // int $month [, int $day [, int $year ]]]]]]
  return mktime($t['tm_hour'], $t['tm_min'], $t['tm_sec'],
  $t['tm_mon'], $t['tm_day'], $t['tm_year']);
  }
  }
 
  /**
  * This class performs parsing of XRDS documents.
  *
  * You should not instantiate this class directly; rather, call
  * parseXRDS statically:
  *
  * <pre> $xrds = Auth_Yadis_XRDS::parseXRDS($xml_string);</pre>
  *
  * If the XRDS can be parsed and is valid, an instance of
  * Auth_Yadis_XRDS will be returned. Otherwise, null will be
  * returned. This class is used by the Auth_Yadis_Yadis::discover
  * method.
  *
  * @package OpenID
  */
  class Auth_Yadis_XRDS {
 
  /**
  * Instantiate a Auth_Yadis_XRDS object. Requires an XPath
  * instance which has been used to parse a valid XRDS document.
  */
  function Auth_Yadis_XRDS($xmlParser, $xrdNodes)
  {
  $this->parser = $xmlParser;
  $this->xrdNode = $xrdNodes[count($xrdNodes) - 1];
  $this->allXrdNodes = $xrdNodes;
  $this->serviceList = array();
  $this->_parse();
  }
 
  /**
  * Parse an XML string (XRDS document) and return either a
  * Auth_Yadis_XRDS object or null, depending on whether the
  * XRDS XML is valid.
  *
  * @param string $xml_string An XRDS XML string.
  * @return mixed $xrds An instance of Auth_Yadis_XRDS or null,
  * depending on the validity of $xml_string
  */
  static function parseXRDS($xml_string, $extra_ns_map = null)
  {
  $_null = null;
 
  if (!$xml_string) {
  return $_null;
  }
 
  $parser = Auth_Yadis_getXMLParser();
 
  $ns_map = Auth_Yadis_getNSMap();
 
  if ($extra_ns_map && is_array($extra_ns_map)) {
  $ns_map = array_merge($ns_map, $extra_ns_map);
  }
 
  if (!($parser && $parser->init($xml_string, $ns_map))) {
  return $_null;
  }
 
  // Try to get root element.
  $root = $parser->evalXPath('/xrds:XRDS[1]');
  if (!$root) {
  return $_null;
  }
 
  if (is_array($root)) {
  $root = $root[0];
  }
 
  $attrs = $parser->attributes($root);
 
  if (array_key_exists('xmlns:xrd', $attrs) &&
  $attrs['xmlns:xrd'] != Auth_Yadis_XMLNS_XRDS) {
  return $_null;
  } else if (array_key_exists('xmlns', $attrs) &&
  preg_match('/xri/', $attrs['xmlns']) &&
  $attrs['xmlns'] != Auth_Yadis_XMLNS_XRD_2_0) {
  return $_null;
  }
 
  // Get the last XRD node.
  $xrd_nodes = $parser->evalXPath('/xrds:XRDS[1]/xrd:XRD');
 
  if (!$xrd_nodes) {
  return $_null;
  }
 
  $xrds = new Auth_Yadis_XRDS($parser, $xrd_nodes);
  return $xrds;
  }
 
  /**
  * @access private
  */
  function _addService($priority, $service)
  {
  $priority = intval($priority);
 
  if (!array_key_exists($priority, $this->serviceList)) {
  $this->serviceList[$priority] = array();
  }
 
  $this->serviceList[$priority][] = $service;
  }
 
  /**
  * Creates the service list using nodes from the XRDS XML
  * document.
  *
  * @access private
  */
  function _parse()
  {
  $this->serviceList = array();
 
  $services = $this->parser->evalXPath('xrd:Service', $this->xrdNode);
 
  foreach ($services as $node) {
  $s = new Auth_Yadis_Service();
  $s->element = $node;
  $s->parser = $this->parser;
 
  $priority = $s->getPriority();
 
  if ($priority === null) {
  $priority = SERVICES_YADIS_MAX_PRIORITY;
  }
 
  $this->_addService($priority, $s);
  }
  }
 
  /**
  * Returns a list of service objects which correspond to <Service>
  * elements in the XRDS XML document for this object.
  *
  * Optionally, an array of filter callbacks may be given to limit
  * the list of returned service objects. Furthermore, the default
  * mode is to return all service objects which match ANY of the
  * specified filters, but $filter_mode may be
  * SERVICES_YADIS_MATCH_ALL if you want to be sure that the
  * returned services match all the given filters. See {@link
  * Auth_Yadis_Yadis} for detailed usage information on filter
  * functions.
  *
  * @param mixed $filters An array of callbacks to filter the
  * returned services, or null if all services are to be returned.
  * @param integer $filter_mode SERVICES_YADIS_MATCH_ALL or
  * SERVICES_YADIS_MATCH_ANY, depending on whether the returned
  * services should match ALL or ANY of the specified filters,
  * respectively.
  * @return mixed $services An array of {@link
  * Auth_Yadis_Service} objects if $filter_mode is a valid
  * mode; null if $filter_mode is an invalid mode (i.e., not
  * SERVICES_YADIS_MATCH_ANY or SERVICES_YADIS_MATCH_ALL).
  */
  function services($filters = null,
  $filter_mode = SERVICES_YADIS_MATCH_ANY)
  {
 
  $pri_keys = array_keys($this->serviceList);
  sort($pri_keys, SORT_NUMERIC);
 
  // If no filters are specified, return the entire service
  // list, ordered by priority.
  if (!$filters ||
  (!is_array($filters))) {
 
  $result = array();
  foreach ($pri_keys as $pri) {
  $result = array_merge($result, $this->serviceList[$pri]);
  }
 
  return $result;
  }
 
  // If a bad filter mode is specified, return null.
  if (!in_array($filter_mode, array(SERVICES_YADIS_MATCH_ANY,
  SERVICES_YADIS_MATCH_ALL))) {
  return null;
  }
 
  // Otherwise, use the callbacks in the filter list to
  // determine which services are returned.
  $filtered = array();
 
  foreach ($pri_keys as $priority_value) {
  $service_obj_list = $this->serviceList[$priority_value];
 
  foreach ($service_obj_list as $service) {
 
  $matches = 0;
 
  foreach ($filters as $filter) {
 
  if (call_user_func_array($filter, array($service))) {
  $matches++;
 
  if ($filter_mode == SERVICES_YADIS_MATCH_ANY) {
  $pri = $service->getPriority();
  if ($pri === null) {
  $pri = SERVICES_YADIS_MAX_PRIORITY;
  }
 
  if (!array_key_exists($pri, $filtered)) {
  $filtered[$pri] = array();
  }
 
  $filtered[$pri][] = $service;
  break;
  }
  }
  }
 
  if (($filter_mode == SERVICES_YADIS_MATCH_ALL) &&
  ($matches == count($filters))) {
 
  $pri = $service->getPriority();
  if ($pri === null) {
  $pri = SERVICES_YADIS_MAX_PRIORITY;
  }
 
  if (!array_key_exists($pri, $filtered)) {
  $filtered[$pri] = array();
  }
  $filtered[$pri][] = $service;
  }
  }
  }
 
  $pri_keys = array_keys($filtered);
  sort($pri_keys, SORT_NUMERIC);
 
  $result = array();
  foreach ($pri_keys as $pri) {
  $result = array_merge($result, $filtered[$pri]);
  }
 
  return $result;
  }
  }
 
 
file:b/lib/openid.php (new)
  <?php
  /**
  * This class provides a simple interface for OpenID (1.1 and 2.0) authentication.
  * Supports Yadis discovery.
  * The authentication process is stateless/dumb.
  *
  * Usage:
  * Sign-on with OpenID is a two step process:
  * Step one is authentication with the provider:
  * <code>
  * $openid = new LightOpenID('my-host.example.org');
  * $openid->identity = 'ID supplied by user';
  * header('Location: ' . $openid->authUrl());
  * </code>
  * The provider then sends various parameters via GET, one of them is openid_mode.
  * Step two is verification:
  * <code>
  * if ($this->data['openid_mode']) {
  * $openid = new LightOpenID('my-host.example.org');
  * echo $openid->validate() ? 'Logged in.' : 'Failed';
  * }
  * </code>
  *
  * Change the 'my-host.example.org' to your domain name. Do NOT use $_SERVER['HTTP_HOST']
  * for that, unless you know what you are doing.
  *
  * Optionally, you can set $returnUrl and $realm (or $trustRoot, which is an alias).
  * The default values for those are:
  * $openid->realm = (!empty($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $_SERVER['HTTP_HOST'];
  * $openid->returnUrl = $openid->realm . $_SERVER['REQUEST_URI'];
  * If you don't know their meaning, refer to any openid tutorial, or specification. Or just guess.
  *
  * AX and SREG extensions are supported.
  * To use them, specify $openid->required and/or $openid->optional before calling $openid->authUrl().
  * These are arrays, with values being AX schema paths (the 'path' part of the URL).
  * For example:
  * $openid->required = array('namePerson/friendly', 'contact/email');
  * $openid->optional = array('namePerson/first');
  * If the server supports only SREG or OpenID 1.1, these are automaticaly
  * mapped to SREG names, so that user doesn't have to know anything about the server.
  *
  * To get the values, use $openid->getAttributes().
  *
  *
  * The library requires PHP >= 5.1.2 with curl or http/https stream wrappers enabled.
  * @author Mewp
  * @copyright Copyright (c) 2010, Mewp
  * @license http://www.opensource.org/licenses/mit-license.php MIT
  */
  class LightOpenID
  {
  public $returnUrl
  , $required = array()
  , $optional = array()
  , $verify_peer = null
  , $capath = null
  , $cainfo = null
  , $data;
  private $identity, $claimed_id;
  protected $server, $version, $trustRoot, $aliases, $identifier_select = false
  , $ax = false, $sreg = false, $setup_url = null;
  static protected $ax_to_sreg = array(
  'namePerson/friendly' => 'nickname',
  'contact/email' => 'email',
  'namePerson' => 'fullname',
  'birthDate' => 'dob',
  'person/gender' => 'gender',
  'contact/postalCode/home' => 'postcode',
  'contact/country/home' => 'country',
  'pref/language' => 'language',
  'pref/timezone' => 'timezone',
  );
 
  function __construct($host)
  {
  $this->trustRoot = (strpos($host, '://') ? $host : 'http://' . $host);
  if ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off')
  || (isset($_SERVER['HTTP_X_FORWARDED_PROTO'])
  && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
  ) {
  $this->trustRoot = (strpos($host, '://') ? $host : 'https://' . $host);
  }
 
  if(($host_end = strpos($this->trustRoot, '/', 8)) !== false) {
  $this->trustRoot = substr($this->trustRoot, 0, $host_end);
  }
 
  $uri = rtrim(preg_replace('#((?<=\?)|&)openid\.[^&]+#', '', $_SERVER['REQUEST_URI']), '?');
  $this->returnUrl = $this->trustRoot . $uri;
 
  $this->data = ($_SERVER['REQUEST_METHOD'] === 'POST') ? $_POST : $_GET;
 
  if(!function_exists('curl_init') && !in_array('https', stream_get_wrappers())) {
  throw new ErrorException('You must have either https wrappers or curl enabled.');
  }
  }
 
  function __set($name, $value)
  {
  switch ($name) {
  case 'identity':
  if (strlen($value = trim((String) $value))) {
  if (preg_match('#^xri:/*#i', $value, $m)) {
  $value = substr($value, strlen($m[0]));
  } elseif (!preg_match('/^(?:[=@+\$!\(]|https?:)/i', $value)) {
  $value = "http://$value";
  }
  if (preg_match('#^https?://[^/]+$#i', $value, $m)) {
  $value .= '/';
  }
  }
  $this->$name = $this->claimed_id = $value;
  break;
  case 'trustRoot':
  case 'realm':
  $this->trustRoot = trim($value);
  }
  }
 
  function __get($name)
  {
  switch ($name) {
  case 'identity':
  # We return claimed_id instead of identity,
  # because the developer should see the claimed identifier,
  # i.e. what he set as identity, not the op-local identifier (which is what we verify)
  return $this->claimed_id;
  case 'trustRoot':
  case 'realm':
  return $this->trustRoot;
  case 'mode':
  return empty($this->data['openid_mode']) ? null : $this->data['openid_mode'];
  }
  }
 
  /**
  * Checks if the server specified in the url exists.
  *
  * @param $url url to check
  * @return true, if the server exists; false otherwise
  */
  function hostExists($url)
  {
  if (strpos($url, '/') === false) {
  $server = $url;
  } else {
  $server = @parse_url($url, PHP_URL_HOST);
  }
 
  if (!$server) {
  return false;
  }
 
  return !!gethostbynamel($server);
  }
 
  protected function request_curl($url, $method='GET', $params=array())
  {
  $params = http_build_query($params, '', '&');
  $curl = curl_init($url . ($method == 'GET' && $params ? '?' . $params : ''));
  curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($curl, CURLOPT_HEADER, false);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/xrds+xml, */*'));
 
  if($this->verify_peer !== null) {
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, $this->verify_peer);
  if($this->capath) {
  curl_setopt($curl, CURLOPT_CAPATH, $this->capath);
  }
 
  if($this->cainfo) {
  curl_setopt($curl, CURLOPT_CAINFO, $this->cainfo);
  }
  }
 
  if ($method == 'POST') {
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
  } elseif ($method == 'HEAD') {
  curl_setopt($curl, CURLOPT_HEADER, true);
  curl_setopt($curl, CURLOPT_NOBODY, true);
  } else {
  curl_setopt($curl, CURLOPT_HTTPGET, true);
  }
  $response = curl_exec($curl);
 
  if($method == 'HEAD') {
  $headers = array();
  foreach(explode("\n", $response) as $header) {
  $pos = strpos($header,':');
  $name = strtolower(trim(substr($header, 0, $pos)));
  $headers[$name] = trim(substr($header, $pos+1));
  }
 
  # Updating claimed_id in case of redirections.
  $effective_url = curl_getinfo($curl, CURLINFO_EFFECTIVE_URL);
  if($effective_url != $url) {
  $this->identity = $this->claimed_id = $effective_url;
  }
 
  return $headers;
  }
 
  if (curl_errno($curl)) {
  throw new ErrorException(curl_error($curl), curl_errno($curl));
  }
 
  return $response;
  }
 
  protected function request_streams($url, $method='GET', $params=array())
  {
  if(!$this->hostExists($url)) {
  throw new ErrorException("Could not connect to $url.", 404);
  }
 
  $params = http_build_query($params, '', '&');
  switch($method) {
  case 'GET':
  $opts = array(
  'http' => array(
  'method' => 'GET',
  'header' => 'Accept: application/xrds+xml, */*',
  'ignore_errors' => true,
  ), 'ssl' => array(
  'CN_match' => parse_url($url, PHP_URL_HOST),
  ),
  );
  $url = $url . ($params ? '?' . $params : '');
  break;
  case 'POST':
  $opts = array(
  'http' => array(
  'method' => 'POST',
  'header' => 'Content-type: application/x-www-form-urlencoded',
  'content' => $params,
  'ignore_errors' => true,
  ), 'ssl' => array(
  'CN_match' => parse_url($url, PHP_URL_HOST),
  ),
  );
  break;
  case 'HEAD':
  # We want to send a HEAD request,
  # but since get_headers doesn't accept $context parameter,
  # we have to change the defaults.
  $default = stream_context_get_options(stream_context_get_default());
  stream_context_get_default(
  array(
  'http' => array(
  'method' => 'HEAD',
  'header' => 'Accept: application/xrds+xml, */*',
  'ignore_errors' => true,
  ), 'ssl' => array(
  'CN_match' => parse_url($url, PHP_URL_HOST),
  ),
  )
  );
 
  $url = $url . ($params ? '?' . $params : '');
  $headers_tmp = get_headers ($url);
  if(!$headers_tmp) {
  return array();
  }
 
  # Parsing headers.
  $headers = array();
  foreach($headers_tmp as $header) {
  $pos = strpos($header,':');
  $name = strtolower(trim(substr($header, 0, $pos)));
  $headers[$name] = trim(substr($header, $pos+1));
 
  # Following possible redirections. The point is just to have
  # claimed_id change with them, because get_headers() will
  # follow redirections automatically.
  # We ignore redirections with relative paths.
  # If any known provider uses them, file a bug report.
  if($name == 'location') {
  if(strpos($headers[$name], 'http') === 0) {
  $this->identity = $this->claimed_id = $headers[$name];
  } elseif($headers[$name][0] == '/') {
  $parsed_url = parse_url($this->claimed_id);
  $this->identity =
  $this->claimed_id = $parsed_url['scheme'] . '://'
  . $parsed_url['host']
  . $headers[$name];
  }
  }
  }
 
  # And restore them.
  stream_context_get_default($default);
  return $headers;
  }
 
  if($this->verify_peer) {
  $opts['ssl'] += array(
  'verify_peer' => true,
  'capath' => $this->capath,
  'cafile' => $this->cainfo,
  );
  }
 
  $context = stream_context_create ($opts);
 
  return file_get_contents($url, false, $context);
  }
 
  protected function request($url, $method='GET', $params=array())
  {
  if (function_exists('curl_init')
  && (!in_array('https', stream_get_wrappers()) || !ini_get('safe_mode') && !ini_get('open_basedir'))
  ) {
  return $this->request_curl($url, $method, $params);
  }
  return $this->request_streams($url, $method, $params);
  }
 
  protected function build_url($url, $parts)
  {
  if (isset($url['query'], $parts['query'])) {
  $parts['query'] = $url['query'] . '&' . $parts['query'];
  }
 
  $url = $parts + $url;
  $url = $url['scheme'] . '://'
  . (empty($url['username'])?''
  :(empty($url['password'])? "{$url['username']}@"
  :"{$url['username']}:{$url['password']}@"))
  . $url['host']
  . (empty($url['port'])?'':":{$url['port']}")
  . (empty($url['path'])?'':$url['path'])
  . (empty($url['query'])?'':"?{$url['query']}")
  . (empty($url['fragment'])?'':"#{$url['fragment']}");
  return $url;
  }
 
  /**
  * Helper function used to scan for <meta>/<link> tags and extract information
  * from them
  */
  protected function htmlTag($content, $tag, $attrName, $attrValue, $valueName)
  {
  preg_match_all("#<{$tag}[^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*$valueName=['\"](.+?)['\"][^>]*/?>#i", $content, $matches1);
  preg_match_all("#<{$tag}[^>]*$valueName=['\"](.+?)['\"][^>]*$attrName=['\"].*?$attrValue.*?['\"][^>]*/?>#i", $content, $matches2);
 
  $result = array_merge($matches1[1], $matches2[1]);
  return empty($result)?false:$result[0];
  }
 
  /**
  * Performs Yadis and HTML discovery. Normally not used.
  * @param $url Identity URL.
  * @return String OP Endpoint (i.e. OpenID provider address).
  * @throws ErrorException
  */
  function discover($url)
  {
  if (!$url) throw new ErrorException('No identity supplied.');
  # Use xri.net proxy to resolve i-name identities
  if (!preg_match('#^https?:#', $url)) {
  $url = "https://xri.net/$url";
  }
 
  # We save the original url in case of Yadis discovery failure.
  # It can happen when we'll be lead to an XRDS document
  # which does not have any OpenID2 services.
  $originalUrl = $url;
 
  # A flag to disable yadis discovery in case of failure in headers.
  $yadis = true;
 
  # We'll jump a maximum of 5 times, to avoid endless redirections.
  for ($i = 0; $i < 5; $i ++) {
  if ($yadis) {
  $headers = $this->request($url, 'HEAD');
 
  $next = false;
  if (isset($headers['x-xrds-location'])) {
  $url = $this->build_url(parse_url($url), parse_url(trim($headers['x-xrds-location'])));
  $next = true;
  }
 
  if (isset($headers['content-type'])
  && (strpos($headers['content-type'], 'application/xrds+xml') !== false
  || strpos($headers['content-type'], 'text/xml') !== false)
  ) {
  # Apparently, some providers return XRDS documents as text/html.
  # While it is against the spec, allowing this here shouldn't break
  # compatibility with anything.
  # ---
  # Found an XRDS document, now let's find the server, and optionally delegate.
  $content = $this->request($url, 'GET');
 
  preg_match_all('#<Service.*?>(.*?)</Service>#s', $content, $m);
  foreach($m[1] as $content) {
  $content = ' ' . $content; # The space is added, so that strpos doesn't return 0.
 
  # OpenID 2
  $ns = preg_quote('http://specs.openid.net/auth/2.0/');
  if(preg_match('#<Type>\s*'.$ns.'(server|signon)\s*</Type>#s', $content, $type)) {
  if ($type[1] == 'server') $this->identifier_select = true;
 
  preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
  preg_match('#<(Local|Canonical)ID>(.*)</\1ID>#', $content, $delegate);
  if (empty($server)) {
  return false;
  }
  # Does the server advertise support for either AX or SREG?
  $this->ax = (bool) strpos($content, '<Type>http://openid.net/srv/ax/1.0</Type>');
  $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
  || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
 
  $server = $server[1];
  if (isset($delegate[2])) $this->identity = trim($delegate[2]);
  $this->version = 2;
 
  $this->server = $server;
  return $server;
  }
 
  # OpenID 1.1
  $ns = preg_quote('http://openid.net/signon/1.1');
  if (preg_match('#<Type>\s*'.$ns.'\s*</Type>#s', $content)) {
 
  preg_match('#<URI.*?>(.*)</URI>#', $content, $server);
  preg_match('#<.*?Delegate>(.*)</.*?Delegate>#', $content, $delegate);
  if (empty($server)) {
  return false;
  }
  # AX can be used only with OpenID 2.0, so checking only SREG
  $this->sreg = strpos($content, '<Type>http://openid.net/sreg/1.0</Type>')
  || strpos($content, '<Type>http://openid.net/extensions/sreg/1.1</Type>');
 
  $server = $server[1];
  if (isset($delegate[1])) $this->identity = $delegate[1];
  $this->version = 1;
 
  $this->server = $server;
  return $server;
  }
  }
 
  $next = true;
  $yadis = false;
  $url = $originalUrl;
  $content = null;
  break;
  }
  if ($next) continue;
 
  # There are no relevant information in headers, so we search the body.
  $content = $this->request($url, 'GET');
  $location = $this->htmlTag($content, 'meta', 'http-equiv', 'X-XRDS-Location', 'content');
  if ($location) {
  $url = $this->build_url(parse_url($url), parse_url($location));
  continue;
  }
  }
 
  if (!$content) $content = $this->request($url, 'GET');
 
  # At this point, the YADIS Discovery has failed, so we'll switch
  # to openid2 HTML discovery, then fallback to openid 1.1 discovery.
  $server = $this->htmlTag($content, 'link', 'rel', 'openid2.provider', 'href');
  $delegate = $this->htmlTag($content, 'link', 'rel', 'openid2.local_id', 'href');
  $this->version = 2;
 
  if (!$server) {
  # The same with openid 1.1
  $server = $this->htmlTag($content, 'link', 'rel', 'openid.server', 'href');
  $delegate = $this->htmlTag($content, 'link', 'rel', 'openid.delegate', 'href');
  $this->version = 1;
  }
 
  if ($server) {
  # We found an OpenID2 OP Endpoint
  if ($delegate) {
  # We have also found an OP-Local ID.
  $this->identity = $delegate;
  }
  $this->server = $server;
  return $server;
  }
 
  throw new ErrorException("No OpenID Server found at $url", 404);
  }
  throw new ErrorException('Endless redirection!', 500);
  }
 
  protected function sregParams()
  {
  $params = array();
  # We always use SREG 1.1, even if the server is advertising only support for 1.0.
  # That's because it's fully backwards compatibile with 1.0, and some providers
  # advertise 1.0 even if they accept only 1.1. One such provider is myopenid.com
  $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1';
  if ($this->required) {
  $params['openid.sreg.required'] = array();
  foreach ($this->required as $required) {
  if (!isset(self::$ax_to_sreg[$required])) continue;
  $params['openid.sreg.required'][] = self::$ax_to_sreg[$required];
  }
  $params['openid.sreg.required'] = implode(',', $params['openid.sreg.required']);
  }
 
  if ($this->optional) {
  $params['openid.sreg.optional'] = array();
  foreach ($this->optional as $optional) {
  if (!isset(self::$ax_to_sreg[$optional])) continue;
  $params['openid.sreg.optional'][] = self::$ax_to_sreg[$optional];
  }
  $params['openid.sreg.optional'] = implode(',', $params['openid.sreg.optional']);
  }
  return $params;
  }
 
  protected function axParams()
  {
  $params = array();
  if ($this->required || $this->optional) {
  $params['openid.ns.ax'] = 'http://openid.net/srv/ax/1.0';
  $params['openid.ax.mode'] = 'fetch_request';
  $this->aliases = array();
  $counts = array();
  $required = array();
  $optional = array();
  foreach (array('required','optional') as $type) {
  foreach ($this->$type as $alias => $field) {
  if (is_int($alias)) $alias = strtr($field, '/', '_');
  $this->aliases[$alias] = 'http://axschema.org/' . $field;
  if (empty($counts[$alias])) $counts[$alias] = 0;
  $counts[$alias] += 1;
  ${$type}[] = $alias;
  }
  }
  foreach ($this->aliases as $alias => $ns) {
  $params['openid.ax.type.' . $alias] = $ns;
  }
  foreach ($counts as $alias => $count) {
  if ($count == 1) continue;
  $params['openid.ax.count.' . $alias] = $count;
  }
 
  # Don't send empty ax.requied and ax.if_available.
  # Google and possibly other providers refuse to support ax when one of these is empty.
  if($required) {
  $params['openid.ax.required'] = implode(',', $required);
  }
  if($optional) {
  $params['openid.ax.if_available'] = implode(',', $optional);
  }
  }
  return $params;
  }
 
  protected function authUrl_v1($immediate)
  {
  $returnUrl = $this->returnUrl;
  # If we have an openid.delegate that is different from our claimed id,
  # we need to somehow preserve the claimed id between requests.
  # The simplest way is to just send it along with the return_to url.
  if($this->identity != $this->claimed_id) {
  $returnUrl .= (strpos($returnUrl, '?') ? '&' : '?') . 'openid.claimed_id=' . $this->claimed_id;
  }
 
  $params = array(
  'openid.return_to' => $returnUrl,
  'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
  'openid.identity' => $this->identity,
  'openid.trust_root' => $this->trustRoot,
  ) + $this->sregParams();
 
  return $this->build_url(parse_url($this->server)
  , array('query' => http_build_query($params, '', '&')));
  }
 
  protected function authUrl_v2($immediate)
  {
  $params = array(
  'openid.ns' => 'http://specs.openid.net/auth/2.0',
  'openid.mode' => $immediate ? 'checkid_immediate' : 'checkid_setup',
  'openid.return_to' => $this->returnUrl,
  'openid.realm' => $this->trustRoot,
  );
  if ($this->ax) {
  $params += $this->axParams();
  }
  if ($this->sreg) {
  $params += $this->sregParams();
  }
  if (!$this->ax && !$this->sreg) {
  # If OP doesn't advertise either SREG, nor AX, let's send them both
  # in worst case we don't get anything in return.
  $params += $this->axParams() + $this->sregParams();
  }
 
  if ($this->identifier_select) {
  $params['openid.identity'] = $params['openid.claimed_id']
  = 'http://specs.openid.net/auth/2.0/identifier_select';
  } else {
  $params['openid.identity'] = $this->identity;
  $params['openid.claimed_id'] = $this->claimed_id;
  }
 
  return $this->build_url(parse_url($this->server)
  , array('query' => http_build_query($params, '', '&')));
  }
 
  /**
  * Returns authentication url. Usually, you want to redirect your user to it.
  * @return String The authentication url.
  * @param String $select_identifier Whether to request OP to select identity for an user in OpenID 2. Does not affect OpenID 1.
  * @throws ErrorException
  */
  function authUrl($immediate = false)
  {
  if ($this->setup_url && !$immediate) return $this->setup_url;
  if (!$this->server) $this->discover($this->identity);
 
  if ($this->version == 2) {
  return $this->authUrl_v2($immediate);
  }
  return $this->authUrl_v1($immediate);
  }
 
  /**
  * Performs OpenID verification with the OP.
  * @return Bool Whether the verification was successful.
  * @throws ErrorException
  */
  function validate()
  {
  # If the request was using immediate mode, a failure may be reported
  # by presenting user_setup_url (for 1.1) or reporting
  # mode 'setup_needed' (for 2.0). Also catching all modes other than
  # id_res, in order to avoid throwing errors.
  if(isset($this->data['openid_user_setup_url'])) {
  $this->setup_url = $this->data['openid_user_setup_url'];
  return false;
  }
  if($this->mode != 'id_res') {
  return false;
  }
 
  $this->claimed_id = isset($this->data['openid_claimed_id'])?$this->data['openid_claimed_id']:$this->data['openid_identity'];
  $params = array(
  'openid.assoc_handle' => $this->data['openid_assoc_handle'],
  'openid.signed' => $this->data['openid_signed'],
  'openid.sig' => $this->data['openid_sig'],
  );
 
  if (isset($this->data['openid_ns'])) {
  # We're dealing with an OpenID 2.0 server, so let's set an ns
  # Even though we should know location of the endpoint,
  # we still need to verify it by discovery, so $server is not set here
  $params['openid.ns'] = 'http://specs.openid.net/auth/2.0';
  } elseif (isset($this->data['openid_claimed_id'])
  && $this->data['openid_claimed_id'] != $this->data['openid_identity']
  ) {
  # If it's an OpenID 1 provider, and we've got claimed_id,
  # we have to append it to the returnUrl, like authUrl_v1 does.
  $this->returnUrl .= (strpos($this->returnUrl, '?') ? '&' : '?')
  . 'openid.claimed_id=' . $this->claimed_id;
  }
 
  if ($this->data['openid_return_to'] != $this->returnUrl) {
  # The return_to url must match the url of current request.
  # I'm assuing that noone will set the returnUrl to something that doesn't make sense.
  return false;
  }
 
  $server = $this->discover($this->claimed_id);
 
  foreach (explode(',', $this->data['openid_signed']) as $item) {
  # Checking whether magic_quotes_gpc is turned on, because
  # the function may fail if it is. For example, when fetching
  # AX namePerson, it might containg an apostrophe, which will be escaped.
  # In such case, validation would fail, since we'd send different data than OP
  # wants to verify. stripslashes() should solve that problem, but we can't
  # use it when magic_quotes is off.
  $value = $this->data['openid_' . str_replace('.','_',$item)];
  $params['openid.' . $item] = get_magic_quotes_gpc() ? stripslashes($value) : $value;
 
  }
 
  $params['openid.mode'] = 'check_authentication';
 
  $response = $this->request($server, 'POST', $params);
 
  return preg_match('/is_valid\s*:\s*true/i', $response);
  }
 
  protected function getAxAttributes()
  {
  $alias = null;
  if (isset($this->data['openid_ns_ax'])
  && $this->data['openid_ns_ax'] != 'http://openid.net/srv/ax/1.0'
  ) { # It's the most likely case, so we'll check it before
  $alias = 'ax';
  } else {
  # 'ax' prefix is either undefined, or points to another extension,
  # so we search for another prefix
  foreach ($this->data as $key => $val) {
  if (substr($key, 0, strlen('openid_ns_')) == 'openid_ns_'
  && $val == 'http://openid.net/srv/ax/1.0'
  ) {
  $alias = substr($key, strlen('openid_ns_'));
  break;
  }
  }
  }
  if (!$alias) {
  # An alias for AX schema has not been found,
  # so there is no AX data in the OP's response
  return array();
  }
 
  $attributes = array();
  foreach (explode(',', $this->data['openid_signed']) as $key) {
  $keyMatch = $alias . '.value.';
  if (substr($key, 0, strlen($keyMatch)) != $keyMatch) {
  continue;
  }
  $key = substr($key, strlen($keyMatch));
  if (!isset($this->data['openid_' . $alias . '_type_' . $key])) {
  # OP is breaking the spec by returning a field without
  # associated ns. This shouldn't happen, but it's better
  # to check, than cause an E_NOTICE.
  continue;
  }
  $value = $this->data['openid_' . $alias . '_value_' . $key];
  $key = substr($this->data['openid_' . $alias . '_type_' . $key],
  strlen('http://axschema.org/'));
 
  $attributes[$key] = $value;
  }
  return $attributes;
  }
 
  protected function getSregAttributes()
  {
  $attributes = array();
  $sreg_to_ax = array_flip(self::$ax_to_sreg);
  foreach (explode(',', $this->data['openid_signed']) as $key) {
  $keyMatch = 'sreg.';
  if (substr($key, 0, strlen($keyMatch)) != $keyMatch) {
  continue;
  }
  $key = substr($key, strlen($keyMatch));
  if (!isset($sreg_to_ax[$key])) {
  # The field name isn't part of the SREG spec, so we ignore it.
  continue;
  }
  $attributes[$sreg_to_ax[$key]] = $this->data['openid_sreg_' . $key];
  }
  return $attributes;
  }
 
  /**
  * Gets AX/SREG attributes provided by OP. should be used only after successful validaton.
  * Note that it does not guarantee that any of the required/optional parameters will be present,
  * or that there will be no other attributes besides those specified.
  * In other words. OP may provide whatever information it wants to.
  * * SREG names will be mapped to AX names.
  * * @return Array Array of attributes with keys being the AX schema names, e.g. 'contact/email'
  * @see http://www.axschema.org/types/
  */
  function getAttributes()
  {
  if (isset($this->data['openid_ns'])
  && $this->data['openid_ns'] == 'http://specs.openid.net/auth/2.0'
  ) { # OpenID 2.0
  # We search for both AX and SREG attributes, with AX taking precedence.
  return $this->getAxAttributes() + $this->getSregAttributes();
  }
  return $this->getSregAttributes();
  }
  }
 
file:a/robots.txt -> file:b/robots.txt
User-agent: * User-agent: *
Disallow: /admin Disallow: /admin
  Sitemap: http://contracts.disclosurelo.gs/sitemap.xml.php
file:a/search.php -> file:b/search.php
<?php <?php
   
/* /*
search ABNs search ABNs
search agency name search agency name
search categories search categories
search supplier names search supplier names
--search supplier postcodes/suburbs/cities-- --search supplier postcodes/suburbs/cities--
search CN number search CN number
search description full text search description full text
*/ */
include('./lib/common.inc.php'); include('./lib/common.inc.php');
if ($_REQUEST['searchID']) { if ($_REQUEST['searchID']) {
$searchIDParts = explode("-",$_REQUEST['searchID']); $searchIDParts = explode("-", $_REQUEST['searchID']);
$type = array_shift($searchIDParts); $type = array_shift($searchIDParts);
$host = $_SERVER['HTTP_HOST']; $host = $_SERVER['HTTP_HOST'];
$uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\'); $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\');
if ($type == "agency") { if ($type == "agency") {
header("Location: http://$host$uri/displayAgency.php?agency=".implode("-",$searchIDParts)); header("Location: http://$host$uri/displayAgency.php?agency=" . implode("-", $searchIDParts));
} }
if ($type == "supplier") { if ($type == "supplier") {
header("Location: http://$host$uri/displaySupplier.php?supplier=".implode("-",$searchIDParts)); header("Location: http://$host$uri/displaySupplier.php?supplier=" . implode("-", $searchIDParts));
} }
exit; if ($type == "cnid") {
  header("Location: http://$host$uri/displayContract.php?CNID=" . implode("-", $searchIDParts));
  }
  exit;
} else { } else {
include_header("Search Results"); include_header("Search Results");
print_r($_REQUEST); print_r($_REQUEST);
include_footer(); include_footer();
} }
?> ?>
   
<?php <?php
   
include_once ("./lib/common.inc.php"); include_once ("./lib/common.inc.php");
$input = strtolower($_REQUEST['input']); $input = strtolower($_REQUEST['input']);
$len = strlen($input); $len = strlen($input);
$limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 0; $limit = isset($_GET['limit']) ? (int) $_GET['limit'] : 0;
$aResults = array(); $aResults = array();
$count = 0; $count = 0;
if ($len) { if ($len) {
$query = 'SELECT MAX("supplierName"), MAX("supplierABN"), count(*) as count $query = 'SELECT MAX("supplierName"), MAX("supplierABN"), count(*) as count
FROM contractnotice FROM contractnotice
WHERE "supplierName" ILIKE :supplierName WHERE "supplierName" ILIKE :supplierName
GROUP BY "supplierName" GROUP BY "supplierName"
ORDER BY count(*) DESC ORDER BY count(*) DESC
LIMIT 4; LIMIT 4;
'; ';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$supplierName = $input . '%'; $supplierName = $input . '%';
$query->bindParam(":supplierName", $supplierName); $query->bindParam(":supplierName", $supplierName);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
$count++; $count++;
$aResults[] = array( $aResults[] = array(
"id" => "supplier-" . $row[1] . '-' . $row[0], "id" => "supplier-" . $row[1] . '-' . $row[0],
"value" => htmlspecialchars($row[0]), "value" => htmlspecialchars($row[0]),
"info" => htmlspecialchars("Supplier - " . $row['count'] . " records") "info" => htmlspecialchars("Supplier - " . $row['count'] . " records")
); );
} }
$query = 'SELECT MAX("agencyName"), count(*) as count $query = 'SELECT MAX("agencyName"), count(*) as count
FROM contractnotice FROM contractnotice
WHERE "agencyName" ILIKE :agencyName WHERE "agencyName" ILIKE :agencyName
GROUP BY "agencyName" GROUP BY "agencyName"
ORDER BY count DESC ORDER BY count DESC
LIMIT 4;'; LIMIT 4;';
$query = $conn->prepare($query); $query = $conn->prepare($query);
$agencyName = $input . '%'; $agencyName = $input . '%';
$query->bindParam(":agencyName", $agencyName); $query->bindParam(":agencyName", $agencyName);
$query->execute(); $query->execute();
databaseError($conn->errorInfo()); databaseError($conn->errorInfo());
foreach ($query->fetchAll() as $row) { foreach ($query->fetchAll() as $row) {
$count++; $count++;
$aResults[] = array( $aResults[] = array(
"id" => "agency-" . $row[0], "id" => "agency-" . $row[0],
"value" => htmlspecialchars($row[0]), "value" => htmlspecialchars($row[0]),
"info" => htmlspecialchars("Government Agency - " . $row['count'] . " records") "info" => htmlspecialchars("Government Agency - " . $row['count'] . " records")
); );
} }
  $query = "SELECT \"CNID\", description, value FROM contractnotice
  WHERE to_tsvector('english', description) @@ to_tsquery('english', :input)";
  $query = $conn->prepare($query);
  $agencyName = $input . '%';
  $query->bindParam(":input", $input);
  $query->execute();
  databaseError($conn->errorInfo());
  foreach ($query->fetchAll() as $row) {
  $count++;
  $aResults[] = array(
  "id" => "cnid-" . $row[0],
  "value" => htmlspecialchars($row['description']),
  "info" => htmlspecialchars("Contract Notice - Value ".$row['value'])
  );
  }
} }
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Pragma: no-cache"); // HTTP/1.0 header("Pragma: no-cache"); // HTTP/1.0
if (isset($_REQUEST['json'])) { if (isset($_REQUEST['json'])) {
header("Content-Type: application/json"); header("Content-Type: application/json");
echo "{\"results\": ["; echo "{\"results\": [";
$arr = array(); $arr = array();
for ($i = 0; $i < count($aResults); $i++) { for ($i = 0; $i < count($aResults); $i++) {
$arr[] = "{\"id\": \"" . $aResults[$i]['id'] . "\", \"value\": \"" . $aResults[$i]['value'] . "\", \"info\": \"\"}"; $arr[] = "{\"id\": \"" . $aResults[$i]['id'] . "\", \"value\": \"" . $aResults[$i]['value'] . "\", \"info\": \"\"}";
} }
echo implode(", ", $arr); echo implode(", ", $arr);
echo "]}"; echo "]}";
} else { } else {
header("Content-Type: text/xml"); header("Content-Type: text/xml");
echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?><results>"; echo "<?xml version=\"1.0\" encoding=\"utf-8\" ?><results>";
for ($i = 0; $i < count($aResults); $i++) { for ($i = 0; $i < count($aResults); $i++) {
echo "<rs id=\"" . $aResults[$i]['id'] . "\" info=\"" . $aResults[$i]['info'] . "\">" . $aResults[$i]['value'] . "</rs>"; echo "<rs id=\"" . $aResults[$i]['id'] . "\" info=\"" . $aResults[$i]['info'] . "\">" . $aResults[$i]['value'] . "</rs>";
} }
echo "</results>"; echo "</results>";
} }
?> ?>
<?php <?php
include ('include/common.inc.php'); include ('lib/common.inc.php');
$last_updated = date('Y-m-d',@filemtime('cbrfeed.zip')); $last_updated = date('Y-m-d',@filemtime('cbrfeed.zip'));
header("Content-Type: text/xml"); header("Content-Type: text/xml");
echo "<?xml version='1.0' encoding='UTF-8'?>"; echo "<?xml version='1.0' encoding='UTF-8'?>";
echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n"; echo '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
echo " <url><loc>".curPageURL()."index.php</loc><priority>1.0</priority></url>\n"; echo " <url><loc>".local_url()."index.php</loc><priority>1.0</priority></url>\n";
foreach (scandir("./") as $file) { foreach (scandir("./") as $file) {
if (strpos($file,".php") !== false && $file != "index.php" && $file != "sitemap.xml.php") echo " <url><loc>".curPageURL()."$file</loc><priority>0.3</priority></url>\n"; if (strpos($file,".php") !== false && $file != "index.php" && $file != "sitemap.xml.php") echo " <url><loc>".local_url()."$file</loc><priority>0.3</priority></url>\n";
} }
foreach (getStops() as $stop) {  
echo " <url><loc>".curPageURL()."stop.php?stopid=".htmlspecialchars ($stop["stop_id"])."</loc>";  
echo "<lastmod>" . $last_updated . "</lastmod>";  
echo "<changefreq>monthly</changefreq>";  
echo "<priority>0.9</priority>";  
echo "</url>\n";  
}  
foreach (getRoutes() as $route) {  
echo " <url><loc>".curPageURL()."trip.php?routeid=".htmlspecialchars ($route["route_id"])."</loc>";  
echo "<lastmod>" . $last_updated . "</lastmod>";  
echo "<changefreq>monthly</changefreq>";  
echo "<priority>0.9</priority>";  
echo "</url>\n";  
}  
echo '</urlset>'; echo '</urlset>';
   
?> ?>