www/update.yam.ch/index.php
<?php
/***************************************************************************
YAM - Yet Another Mailer
Copyright (C) 1995-2000 by Marcel Beck <mbeck@yam.ch>
Copyright (C) 2000-2022 YAM Open Source Team
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
YAM Official Support Site : http://www.yam.ch/
YAM OpenSource project : http://sourceforge.net/projects/yamos/
***************************************************************************/
/*
* PHP script to manage the update requests to the http://update.yam.ch/
* web server for checking/notifying clients that certain components are
* available in newer versions.
*
* Requests are commonly formed in the following form and an example
* request might look like:
*
* http://update.yam.ch/?ver=YAM%202%2E6%2Ddev%20%5BOS4%2FPPC%5D&builddate=08%2E02%2E2008&lang=deutsch%206%2E0&exec=52%2E21&lib0=codesets-6%2E5&lib1=amissl-3%2E7&lib2=xpk-5%2E2&lib3=openurl-7%2E2&mui=20%2E2282&mcc0=thebar-26%2E1&mcc1=texteditor-15%2E26&mcc2=betterstring-11%2E14&mcc3=nlist-20%2E120&mcc4=nlistview-19%2E75&mcc5=nfloattext-19%2E56&mcc6=nlisttree-18%2E27
*
*/
// path to the various update directories
$NIGHTLYDIR="updates/nightly";
$STABLEDIR="updates/stable";
$CONTRIBDIR="updates/contrib";
// path to the logfile where we log our visitors/updaters
$LOGFILE="log/updatecheck.log";
// retrieve the data a user might specify on the request URL by using
// an URL similar to: http://update.yam.ch/?ver=2.5&buildid=20060505
// Please note that such URLs have to be properly encoded in the common
// URL encoding format.
$userVERSTR=trim(strtolower($_GET['ver'])); // version (YAM 2.5-dev [OS4/PPC])
$userBUILDID=trim(strtolower($_GET['buildid']), " \t-"); // buildid (20060505)
$userBUILDDATE=trim(strtolower($_GET['builddate'])); // builddate (05.05.2006)
$userLANG=trim(strtolower($_GET['lang'])); // catalog language and version (deutsch 5.5)
$userEXEC=trim(strtolower($_GET['exec'])); // users' exec version (51.16)
$userMUI=trim(strtolower($_GET['mui'])); // users' MUI version (20.1551)
$debug=$_GET['debug']; // if "1" then be more verbose
// before we do anything serious, we do a check if all necessary options
// were specified and if not we simply generate a fake webpage redirecting to the main
// webpage of www.yam.ch
if($userVERSTR == "" || $userBUILDDATE == "")
{
// redirect the user to the download description page
print "<head>";
print "<meta http-equiv='refresh' content='1; URL=http://yam.ch/downloads'>";
print "</head>";
// exit here and do not continue processing
exit;
}
// log the visitor/updater in our logfile first
$ipaddress=$_SERVER['REMOTE_ADDR'];
$referrer=$_SERVER['HTTP_REFERER'];
$datetime=date('Y-m-d H:i:s');
$useragent = $_SERVER['HTTP_USER_AGENT'];
$remotehost = @getHostByAddr($ipaddress);
// open logfile in append mode and output some information for
// statistical purposes. Here we take care not to catch any utterly confidental
// information about the client system. Only the bare minimum like which
// version of YAM and its components and where the request came from.
if($fh = fopen($LOGFILE, 'a+'))
{
$logline = "$datetime: $remotehost [$ipaddress]: $userVERSTR ($userBUILDDATE) - $userLANG - exec $userEXEC - MUI $userMUI\n";
fwrite($fh, $logline);
fclose($fh);
}
// now open a temporary file to which we output all the stuff here
// and afterwards we send it over to the users
$outfile = tempnam("/tmp", "yam");
if($out = fopen($outfile, 'w'))
{
// print out some initial output (version of php script and timestamp
fprintf($out, "<updatecheck>\n");
fprintf($out, "\$VER: updatecheck 1.3 (06.03.2018)\n");
fprintf($out, "TIME: %s\n", $datetime);
// what we have to do now is: check each single component of YAM for
// an eventually existing update and report it to the user
// 1. Check if the user uses a nightly build or not
if(preg_match("/(dev|nightly)/i", $userVERSTR) && (preg_match("^[0-9]+$", $userBUILDID) || $userBUILDID == ""))
$nightly=true;
else
$nightly=false;
// 2. Check for "YAM" update itself
list($prog, $ver, $system) = explode(" ", trim($userVERSTR), 3);
if($nightly == true)
$updateDir = $NIGHTLYDIR;
else
$updateDir = $STABLEDIR;
// extract the real userversion, userrevision and
// patchlevel numbers
list($userVER, $userREV, $userPL) = preg_split("(\.|p|-)", trim($ver), 3);
$userVER = intval($userVER);
$userREV = intval($userREV);
$userPL = intval($userPL);
// analyze the target specification (if present)
if(preg_match("/os4\/ppc/i", $userVERSTR))
$userTARGET = "ppc-amigaos";
elseif(preg_match("/mos\/ppc/i", $userVERSTR))
$userTARGET = "ppc-morphos";
elseif(preg_match("/aros\/x86_64/i", $userVERSTR))
$userTARGET = "x86_64-aros";
elseif(preg_match("/aros\/x86/i", $userVERSTR))
$userTARGET = "i386-aros";
elseif(preg_match("/aros\/ppc/i", $userVERSTR))
$userTARGET = "ppc-aros";
else
$userTARGET = "m68k-amigaos";
// now we should know all major stuff like the version/revision and
// if the user version is a nightly build or not. So what we do now is, that
// we go and check the 'LATEST' file of the stable tree first and in case the
// user is using a nightly build we check against that latest stable version
// as well.
$fh=fopen($STABLEDIR . "/LATEST", 'r');
if($fh)
{
while(!feof($fh))
{
$line = fgets($fh);
list($stableTarget, $stableYAM) = explode(": ", trim($line), 2);
// check if we found the target
if($userTARGET == $stableTarget)
{
// split the stableYAM by version/revision
list($stableVER, $stableREV, $stablePL) = preg_split("(\.|p|-)", trim($stableYAM), 3);
$stableVER = intval($stableVER);
$stableREV = intval($stableREV);
$stablePL = intval($stablePL);
// now break out
break;
}
}
fclose($fh);
}
#printf("%d %d %d : %d %d %d\n", $userVER, $userREV, $userPL, $stableVER, $stableREV, $stablePL);
// now we should know what the very latest stable version is and all the necessary USER
// version information as well. Here we check first for plausible values first or
// something went definitly wrong.
if($userVER >= 2 && $userREV >= 4 && $userPL >= 0 &&
$stableVER >= 2 && $stableREV >= 4 && $stablePL >= 0)
{
// check if the user version is a nightly build and if so we check
// the stable version against the user version and in case the stable version is
// higher than the users' one we suggest the user to update to the very latest
// stable one instead of cross migrating to the next nightly's of the next version
if($nightly == true && ($stableVER < $userVER ||
($stableVER == $userVER && $stableREV < $userREV)))
{
// now we can update the nightly build of the user because the versions
// match each other.
if(file_exists($updateDir . "/" . $userVER . "." . $userREV) &&
$fh = fopen($updateDir . "/" . $userVER . "." . $userREV, 'r'))
{
$updateFound = false;
$changelog = false;
while(!feof($fh))
{
$line = fgets($fh);
list($tag, $value1, $value2, $value3) = explode(" ", trim($line), 4);
if($changelog == true)
fputs($out, $line);
elseif($tag == "VERSION:")
$updateVER = $value1;
elseif($tag == "BUILDID:")
$updateBUILDID = $value1;
elseif($tag == "BUILDDATE:")
{
$updateBUILDDATE = $value1;
// we now check if this update file really carries newer stuff
// or if we simply have to break out here.
if($userBUILDDATE != "" && strtotime($userBUILDDATE) >= strtotime($updateBUILDDATE))
break;
}
elseif($tag == "URL:" && ($value1 == $userTARGET || $value1 == "*"))
{
// output the initial [UPDATE] header only once
if($updateFound == false)
{
fprintf($out, "<component>\n");
fprintf($out, "NAME: YAM\n");
fprintf($out, "TARGET: $userTARGET\n");
if($updateBUILDID != "")
fprintf($out, "RECENT: %s-%s\n", $updateVER, $updateBUILDID);
else
fprintf($out, "RECENT: %s\n", $updateVER);
if($userBUILDID != "")
fprintf($out, "INSTALLED: %s-%s\n", $ver, $userBUILDID);
else
fprintf($out, "INSTALLED: %s\n", $ver);
$updateFound = true;
}
// now we output the "URL:" line
fprintf($out, "URL: %s\n", trim($value2 . " " . $value3));
}
elseif($tag == "CHANGES:")
{
fprintf($out, "<changelog>\n");
$changelog = true;
}
}
if($changelog == true)
fprintf($out, "</changelog>\n");
if($updateFound == true)
fprintf($out, "</component>\n");
fclose($fh);
}
}
else
{
// now we have to check if we should suggest the user to update to the very
// latest stable version available instead
if(file_exists($STABLEDIR . "/" . $stableYAM) &&
$fh = fopen($STABLEDIR . "/" . $stableYAM, 'r'))
{
$updateFound = false;
$changelog = false;
while(!feof($fh))
{
$line = fgets($fh);
list($tag, $value1, $value2, $value3) = explode(" ", trim($line), 4);
if($changelog == true)
fputs($out, $line);
elseif($tag == "VERSION:")
{
$updateVER = $value1;
// check if the version is really newer or equal to the user one
list($updateVERSION, $updateREVISION, $updatePL) = preg_split("(\.|p|-)", trim($updateVER), 3);
$updateVERSION = intval($updateVERSION);
$updateREVISION = intval($updateREVISION);
$updatePL = intval($updatePL);
if($userVER > $updateVERSION ||
($userVER == $updateVERSION && $userREV > $updateREVISION) ||
($userVER == $updateVERSION && $userREV == $updateREVISION && $userPL > $updatePL))
{
break;
}
}
elseif($tag == "BUILDID:")
$updateBUILDID = $value1;
elseif($tag == "BUILDDATE:")
{
$updateBUILDDATE = $value1;
// we now check if this update file really carries newer stuff
// or if we simply have to break out here.
if($userBUILDDATE != "" && strtotime($userBUILDDATE) >= strtotime($updateBUILDDATE))
break;
}
elseif($tag == "URL:" && ($value1 == $userTARGET || $value1 == "*"))
{
// output the initial [UPDATE] header only once
if($updateFound == false)
{
fprintf($out, "<component>\n");
fprintf($out, "NAME: YAM\n");
fprintf($out, "TARGET: $userTARGET\n");
if($updateBUILDID != "")
fprintf($out, "RECENT: %s-%s\n", $updateVER, $updateBUILDID);
else
fprintf($out, "RECENT: %s\n", $updateVER);
if($userBUILDID != "")
fprintf($out, "INSTALLED: %s-%s\n", $ver, $userBUILDID);
else
fprintf($out, "INSTALLED: %s\n", $ver);
$updateFound = true;
}
// now we output the "URL:" line
fprintf($out, "URL: %s\n", trim($value2 . " " . $value3));
}
elseif($tag == "CHANGES:")
{
fprintf($out, "<changelog>\n");
$changelog = true;
}
}
if($changelog == true)
fprintf($out, "</changelog>\n");
if($updateFound == true)
fprintf($out, "</component>\n");
fclose($fh);
}
}
}
/////////////////////
// now that we have checked/analyzed the update status of YAM itself, we can now
// analyze the update status of the contributions including the version of the
// used catalog translations (locale).
// first we check all 'mcc' variables and then the 'lib' variables
// of the update request
for($i=0; $i < 2; $i++)
{
// first check for mcc's then for libraries
if($i == 0)
$var = "mcc";
elseif($i == 1)
$var = "lib";
$j=0;
while(($lib=trim(strtolower($_GET["$var$j"]))) != "")
{
// extract the name and version
list($name, $verstr) = preg_split("(-)", $lib, 2);
// open the version file
if(file_exists($CONTRIBDIR . "/" . $name . ".$var") &&
$fh = fopen($CONTRIBDIR . "/" . $name . ".$var", 'r'))
{
// extract the correct version/revision parts of verstr
list($version, $revision) = preg_split("(\.)", $verstr, 2);
$version = intval($version);
$revision = intval($revision);
$changelog = false;
while(!feof($fh))
{
$line = fgets($fh);
list($tag, $value1, $value2, $value3) = explode(" ", trim($line), 4);
if($changelog == true)
fputs($out, $line);
elseif($tag == "NAME:")
$updateNAME = trim($value1);
elseif($tag == "VERSION:")
{
$updateVER = trim($value1);
// split the VERSION string into version and revision
list($libVersion, $libRevision) = preg_split("(\.)", $updateVER, 2);
$libVersion = intval($libVersion);
$libRevision = intval($libRevision);
// we now check if this update file really carries newer stuff
// or if we simply have to break out here.
if($updateVER == "" ||
$libVersion < $version ||
($libVersion == $version && $libRevision <= $revision))
{
// no update required
$updateFound = false;
break;
}
// issue a new component header
fprintf($out, "<component>\n");
fprintf($out, "NAME: $updateNAME\n");
fprintf($out, "TARGET: $userTARGET\n");
fprintf($out, "RECENT: $libVersion.$libRevision\n");
fprintf($out, "INSTALLED: $version.$revision\n");
// this component requires an update lets notify the user
$updateFound = true;
}
elseif($tag == "BUILDDATE:")
fprintf($out, "BUILDDATE: $value1\n");
elseif($tag == "URL:" && ($value1 == $userTARGET || $value1 == "*"))
fprintf($out, "URL: %s\n", trim($value2 . " " . $value3));
elseif($tag == "CHANGES:")
{
fprintf($out, "<changelog>\n");
$changelog = true;
}
}
if($changelog == true)
fprintf($out, "</changelog>\n");
if($updateFound == true)
fprintf($out, "</component>\n");
fclose($fh);
}
$j++;
}
}
// now close the update information with an </updatecheck> tag.
fprintf($out, "</updatecheck>\n");
fclose($out);
}
// now we should have prepared the temporary file. let's get its
// file size
$outsize = filesize($outfile);
// as YAM 2.5's update check mechanism seems to be broken we
// need to manually add a Content-Length: header with the number
// of bytes the request will sent.
//if(strncasecmp($useragent, "YAM/2.5", 7) == 0)
header("Content-Length: " . $outsize);
// now we open the file again and output it step by step
if($out = fopen($outfile, 'r'))
{
printf("%s", fread($out, $outsize));
fclose($out);
}
unlink($outfile);
?>