Just configured from Wine's GIT

svn path=/; revision=1
This commit is contained in:
2009-10-09 00:08:02 +00:00
commit 2782475c4f
3000 changed files with 59244 additions and 0 deletions

2
include/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
config.php
stderr

1
include/.htaccess Normal file
View File

@@ -0,0 +1 @@
deny from all

628
include/appData.php Normal file
View File

@@ -0,0 +1,628 @@
<?php
/**
* Functions related to application data
*/
require_once(BASE."include/util.php");
class appData
{
var $iId;
var $iAppId;
var $iVersionId;
var $iSubmitterId;
var $sSubmitTime;
var $sDescription;
var $bQueued;
function appData($iId = null, $oRow = null, $oObject = null)
{
if(!$iId && !$oRow)
return;
/* Since all objects stored in the appData table have a number of common
members, we can import such an object into an appData one without
making an SQL query */
if($oObject && $iId)
{
$this->iSubmitterId = $oObject->iSubmitterId;
$this->sDescription = $oObject->sDescription;
$this->iAppId = $oObject->iAppId;
$this->iVersionId = $oObject->iVersionId;
$this->sSubmitTime = $oObject->sSubmitTime;
$this->iId = $iId;
$this->bQueued = $oObject->bQueued;
return;
}
if(!$oRow)
{
$hResult = query_parameters("SELECT * FROM appData WHERE id = '?'", $iId);
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iSubmitterId = $oRow->submitterId;
$this->iAppId = $oRow->appId;
$this->iVersionId = $oRow->versionId;
$this->sSubmitTime = $oRow->submitTime;
$this->iId = $iId;
$this->bQueued = ($oRow->sState == 'accepted') ? false : true;
$this->sDescription = $oRow->description;
}
}
function purge()
{
return $this->delete();
}
function delete()
{
if(!$this->canEdit())
return FALSE;
$sQuery = "DELETE FROM appData WHERE id = '?'";
$hResult = query_parameters($sQuery, $this->iId);
if(!$hResult)
return FALSE;
return $hResult;
}
function reQueue()
{
if(!$this->canEdit())
return FALSE;
$sQuery = "UPDATE appData SET state = '?' WHERE id = '?'";
$hResult = query_parameters($sQuery, 'queued', $this->iId);
if(!$hResult)
return FALSE;
else
return TRUE;
}
function reject()
{
if(!$this->canEdit())
return FALSE;
$sQuery = "UPDATE appData SET state = '?' WHERE id = '?'";
$hResult = query_parameters($sQuery, 'rejected', $this->iId);
if(!$hResult)
return FALSE;
else
return TRUE;
}
function update()
{
if(!$this->canEdit())
return FALSE;
$sQuery = "UPDATE appData SET versionId = '?', appId = '?', description = '?'
WHERE id = '?'";
$hResult = query_parameters($sQuery, $this->iVersionId, $this->iAppId,
$this->sDescription, $this->iId);
if(!$hResult)
return FALSE;
return TRUE;
}
public function objectGetParent($sClass = '')
{
if($this->iVersionId)
return new version($this->iVersionId);
else
return new application($this->iAppId);
}
public function objectSetParent($iNewId, $sClass = '')
{
if($this->iVersionId)
$this->iVersionId = $iNewId;
else
$this->iAppId = $iNewId;
}
function listSubmittedBy($iUserId, $bQueued = true)
{
$sExtra = '';
if($bQueued) // downloadurls are only queued together with versions
$sExtra = " AND appData.type != 'downloadurl' ";
$hResult = query_parameters("SELECT * FROM appData WHERE
appData.submitterId = '?'
AND
appData.state = '?' $sExtra
ORDER BY appData.id",
$iUserId, $bQueued ? 'queued' : 'accepted');
if(!$hResult || !query_num_rows($hResult))
return false;
$oTable = new table();
$oTable->setWidth("100%");
$oTable->setAlign("center");
$oTableRow = new tableRow();
$oTableRow->addTextCell("Version");
$oTableRow->addTextCell("Type");
$oTableRow->addTextCell("Description");
$oTableRow->addTextCell("Submission Date");
if($bQueued)
$oTableRow->addTextCell("Action");
$oTableRow->setClass("color4");
$oTable->addRow($oTableRow);
for($i = 1; $oRow = query_fetch_object($hResult); $i++)
{
$oTableRow = new tableRow();
if($oRow->versionId)
{
$oVersion = new version($oRow->versionId);
$sLink = "<a href=\"".$oVersion->objectMakeUrl()."\">".
$oVersion->fullName($oVersion->iVersionId)."</a>";
} else
{
$oApp = new application($this->appId);
$sLink = $oApp->objectMakeLink();
}
$oTableRow->addTextCell($sLink);
$oTableRow->addTextCell($oRow->type);
$oTableRow->addTextCell($oRow->description);
$oTableRow->addTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime)));
if($bQueued)
{
$oM = new objectManager($oRow->type);
$oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : "");
$shDeleteLink = '<a href="'.$oM->makeUrl("delete", $oRow->id, "Delete entry").'">delete</a>';
$shEditLink = '<a href="'.$oM->makeUrl("edit", $oRow->id, "Edit entry").'">edit</a>';
$oTableRow->addTextCell("[ $shEditLink ] &nbsp; [ $shDeleteLink ]");
}
$oTableRow->setClass(($i % 2) ? "color0" : "color1");
$oTable->addRow($oTableRow);
}
return $oTable->getString();
}
/* Get appData for a given version/application, optionally filter by type */
function getData($iId, $sType, $bIsVersion = TRUE, $bQueued = FALSE, $bRejected = FALSE)
{
$iAppId = 0;
$iVersionId = 0;
if($bIsVersion)
$iVersionId = $iId;
else
$iAppId = $iId;
$sState = objectManager::getStateString($bQueued, $bRejected);
$hResult = query_parameters("SELECT * FROM appData WHERE appId = '?' AND
versionId = '?' AND TYPE = '?' AND state = '?'",
$iAppId, $iVersionId, $sType, $sState);
if(!$hResult || !query_num_rows($hResult))
return FALSE;
return $hResult;
}
function objectGetEntriesCount($sState, $sType = null, $oFilters = null)
{
/* Not implemented for appData */
if($sState == 'rejected')
return FALSE;
$sSelectType = "";
$sWhereFilter = '';
if($oFilters)
{
$aOptions = $oFilters->getOptions();
if($aOptions['appCategory'])
{
$oCategory = new category($aOptions['appCategory']);
$sWhereFilter .= ' AND ' . $oCategory->getSqlQueryPart();
}
}
if(($sState != 'accepted') &&
!$_SESSION['current']->hasPriv("admin"))
{
$sQuery = "SELECT COUNT(DISTINCT appData.id) as count FROM appData,
appMaintainers, appVersion, appFamily WHERE
appFamily.appId = appVersion.appId
AND
appMaintainers.state = 'accepted'
AND
appMaintainers.userId = '?'
AND
(
(
appMaintainers.appId = appFamily.appId
OR
appMaintainers.appId = appVersion.appId
)
AND
appMaintainers.superMaintainer = '1'
AND
(
appData.appId = appMaintainers.appId
OR
(
appData.versionId = appVersion.versionId
AND
appVersion.appId = appMaintainers.appId
)
)
OR
(
appMaintainers.superMaintainer = '0'
AND
appMaintainers.versionId = appVersion.versionId
AND
appMaintainers.versionId = appData.versionId
)
)
AND
appVersion.state = 'accepted'
AND
appFamily.state = 'accepted'$sWhereFilter";
if($sState != 'all')
$sQuery .= " AND appData.state = '$sState'";
if($sType)
{
$sQuery .= " AND type = '?'";
$hResult = query_parameters($sQuery, $_SESSION['current']->iUserId,
$sType);
} else
{
$hResult = query_parameters($sQuery, $_SESSION['current']->iUserId);
}
} else
{
if($sState != 'all')
$sAppDataQueued = " AND appData.state = '$sState'";
else
$sAppDataQueued = '';
if($sType)
$sSelectType = " AND type = '?'";
$sQuery = "(SELECT COUNT(DISTINCT appData.id) as count FROM appData,
appFamily WHERE
(
appData.appId = appFamily.appId
AND
appData.versionId = '0'
)
AND
appFamily.state = 'accepted'$sAppDataQueued$sSelectType$sWhereFilter) UNION
(
SELECT COUNT(DISTINCT appData.id) as count FROM appData,
appFamily, appVersion WHERE
appFamily.appId = appVersion.appId
AND
(
appData.versionId = appVersion.versionId
)
AND
appVersion.state = 'accepted'
AND
appFamily.state = 'accepted'$sAppDataQueued$sSelectType$sWhereFilter)";
if($sType)
$hResult = query_parameters($sQuery, $sType, $sType);
else
$hResult = query_parameters($sQuery);
}
if(!$hResult)
return FALSE;
for($iCount = 0; $oRow = query_fetch_object($hResult);)
$iCount += $oRow->count;
return $iCount;
}
function objectGetHeader($sType)
{
$oTableRow = new TableRow();
$oTableRow->AddTextCell("Submission Date");
$oTableRow->AddTextCell("Submitter");
$oTableRow->AddTextCell("Application");
$oTableRow->AddTextCell("Version");
return $oTableRow;
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true, $sType = null, $oFilters = null)
{
/* Not implemented for appData */
if($sState == 'rejected')
return FALSE;
$sSelectType = "";
$sLimit = "";
$sWhereFilter = '';
if($oFilters)
{
$aOptions = $oFilters->getOptions();
if($aOptions['appCategory'])
{
$oCategory = new category($aOptions['appCategory']);
$sWhereFilter .= ' AND ' . $oCategory->getSqlQueryPart();
}
}
if($sState != 'accepted' && !$_SESSION['current']->hasPriv("admin"))
{
$sQuery = "SELECT DISTINCT appData.* FROM appData, appMaintainers,
appVersion, appFamily WHERE
appFamily.appId = appVersion.appId
AND
appMaintainers.state = 'accepted'
AND
appMaintainers.userId = '?'
AND
(
(
(
appMaintainers.appId = appFamily.appId
OR
appMaintainers.appId = appVersion.appId
)
AND
appMaintainers.superMaintainer = '1'
AND
(
appData.appId = appMaintainers.appId
OR
(
appData.versionId = appVersion.versionId
AND
appVersion.appId = appMaintainers.appId
)
)
)
OR
(
appMaintainers.superMaintainer = '0'
AND
appMaintainers.versionId = appVersion.versionId
AND
appMaintainers.versionId = appData.versionId
)
)
AND
appVersion.state = 'accepted'
AND
appFamily.state = 'accepted'
AND
appData.state = '?'
AND
appData.type = '?'
$sWhereFilter
ORDER BY appFamily.appName";
if(!$iRows && !$iStart)
{
$hResult = query_parameters($sQuery, $_SESSION['current']->iUserId,
$sState, $sType);
} else
{
if(!$iRows)
$iRows = appData::objectGetEntriesCount($sState, $sType, $oFilters);
$sQuery .= " LIMIT ?,?";
$hResult = query_parameters($sQuery, $_SESSION['current']->iUserId,
$sState, $sType,
$iStart, $iRows);
}
} else
{
if($iStart || $iRows)
$sLimit = " LIMIT ?,?";
$sQuery =
"(
SELECT DISTINCT appData.* FROM appData,
appFamily WHERE
(
appData.appId = appFamily.appId
AND
appData.versionId = '0'
)
AND
appFamily.state = 'accepted'
AND
appData.state = '?'
AND
appData.type = '?' $sWhereFilter ORDER BY appFamily.appName $sLimit
)
UNION
(
SELECT DISTINCT appData.* FROM appData,
appFamily, appVersion WHERE
appFamily.appId = appVersion.appId
AND
(
appData.versionId = appVersion.versionId
)
AND
appVersion.state = 'accepted'
AND
appFamily.state = 'accepted'
AND
appData.state = '?'
AND
appData.type = '?' $sWhereFilter ORDER BY appFamily.appName $sLimit
)";
if(!$iRows && !$iStart)
{
$hResult = query_parameters($sQuery, $sState, $sType,
$sState, $sType);
} else
{
if(!$iRows)
$iRows = appData::objectGetEntriesCount($sState, $sType, $oFilters);
$hResult = query_parameters($sQuery, $sState, $sType,
$iStart, $iRows,
$sState, $sType,
$iStart, $iRows);
}
}
if(!$hResult)
return FALSE;
return $hResult;
}
function canEdit()
{
if($_SESSION['current']->hasPriv("admin"))
return TRUE;
if($this)
{
if($this->bQueued && $this->iSubmitterId == $_SESSION['current']->iUserId)
return true;
if($this->iVersionId)
{
$oVersion = new version($this->iVersionId);
if($oVersion->canEdit())
return TRUE;
else
return FALSE;
} else if($this->iAppId)
{
$oApp = new application($this->iAppId);
if($oApp->canEdit())
return TRUE;
else
return FALSE;
} else
return FALSE;
}
}
function mustBeQueued()
{
if($_SESSION['current']->hasPriv("admin"))
return FALSE;
if($this)
{
if($this->iVersionId)
{
$oVersion = new version($this->iVersionId);
if($oVersion->canEdit() && $oVersion->objectGetState() == 'accepted')
return FALSE;
else
return TRUE;
} else if($this->iAppId)
{
$oApp = new application($this->iAppId);
if($oApp->canEdit() && $oApp->objectGetState() == 'accepted')
return FALSE;
else
return TRUE;
} else
return TRUE;
}
}
function objectGetTableRow()
{
$oVersion = new Version($this->iVersionId);
if(!$this->iAppId)
$this->iAppId = $oVersion->iAppId;
$oApp = new Application($this->iAppId);
$oUser = new User($this->iSubmitterId);
$oTableRow = new TableRow();
$oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime)));
$oTableRow->AddTextCell($oUser->objectMakeLink());
$oTableRow->AddTextCell($oApp->objectMakeLink());
$oTableRow->AddTextCell($this->iVersionId ? $oVersion->objectMakeLink() : "N/A");
// create the object manager specific row
$oOMTableRow = new OMTableRow($oTableRow);
return $oOMTableRow;
}
function objectDisplayQueueProcessingHelp()
{
$sHelp = "<p>This is a list of application data submitted by users. ".
"Please inspect the data carefully before accepting or rejecting it.</p>";
echo $sHelp;
}
/* Output the part of an appData editor which is the same for all data types */
function outputEditorGeneric()
{
$oVersion = new version($this->iVersionId);
if($oVersion->iVersionId)
{
$this->iAppId = $oVersion->iAppId;
$sVersionName = $oVersion->objectMakeLink();
}
else
$sVersionName = "N/A";
$oApp = new Application($this->iAppId);
// view application details
echo html_frame_start("New Application Data Form",600,"",0);
echo "<table width='100%' border=0 cellpadding=2 cellspacing=0>\n";
// app name
echo '<tr valign=top><td class=color0><b>App Name</b></td>',"\n";
echo "<td>".$oApp->objectMakeLink()."</td></tr>\n";
// version
echo '<tr valign=top><td class=color0><b>App Version</b></td>',"\n";
echo "<td>$sVersionName</td></tr>\n";
//dataDescription
echo '<tr valign=top><td class=color0><b>Description</b></td>',"\n";
echo '<td><textarea name="sDescription" rows=10 cols=35>'.stripslashes($this->sDescription).'</textarea></td></tr>',"\n";
}
function getDefaultReply()
{
$sReplyText = "Enter a personalized reason for acceptance or rejection of the".
" submitted application data here";
return $sReplyText;
}
function objectGetId()
{
return $this->iId;
}
}
?>

41
include/appdb.php Normal file
View File

@@ -0,0 +1,41 @@
<?php
function log_category_visit($catId)
{
global $REMOTE_ADDR;
$result = query_parameters("SELECT * FROM catHitStats WHERE ip = '?' AND catId = '?'",
$REMOTE_ADDR, $catId);
if($result && query_num_rows($result) == 1)
{
$oStatsRow = query_fetch_object($result);
query_parameters("UPDATE catHitStats SET count = count + 1 WHERE catHitId = '?'",
$oStatsRow->catHitId);
} else
{
query_parameters("INSERT INTO catHitStats (appHitId, time, ip, catId, count) ".
"VALUES (?, ?, '?', '?', '?')",
"null", "null", $REMOTE_ADDR, $catId, "1");
}
}
function log_application_visit($appId)
{
global $REMOTE_ADDR;
$result = query_parameters("SELECT * FROM appHitStats WHERE ip = '?' AND appId = '?'",
$REMOTE_ADDR, $appId);
if($result && query_num_rows($result) == 1)
{
$stats = query_fetch_object($result);
query_parameters("UPDATE appHitStats SET count = count + 1 WHERE appHitId = '?'",
$stats->appHitId);
} else
{
query_parameters("INSERT INTO appHitStats (appHitId, time, ip, appId, count) ".
"VALUES (?, ?, '?', '?', '?')",
"null", "null", $REMOTE_ADDR, $appId, "1");
}
}
?>

1459
include/application.php Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,466 @@
<?php
/**
* Class for submitting/processing applications
*/
class application_queue
{
var $oVersionQueue;
var $oApp;
var $oVendor;
function application_queue($iAppId = null, $oRow = null)
{
$this->oApp = new application($iAppId, $oRow);
$iVersionId = null;
$iVendorId = null;
/* If this is an existing application then there must be a version
accompanying it */
if($this->oApp->iAppId)
{
/* Normal users do not get a aVersionsIds property, so we have to fetch
the versionId manually. Normal users only have access to rejected
applications, unless they submitted them */
if($_SESSION['current']->hasPriv("admin"))
{
$iVersionId = $this->oApp->aVersionsIds[0];
} else if($this->oApp->objectGetState() == 'rejected' ||
($this->oApp->objectGetState() == 'queued' &&
$this->oApp->objectGetSubmitterId() == $_SESSION['current']->iUserId))
{
$sQuery = "SELECT versionId FROM appVersion WHERE appId = '?' LIMIT 1";
$hResult = query_parameters($sQuery, $this->oApp->iAppId);
if($hResult)
{
if($oRow = query_fetch_object($hResult))
$iVersionId = $oRow->versionId;
}
}
$iVendorId = $this->oApp->iVendorId;
}
$this->oVendor = new vendor($iVendorId);
$this->oVersionQueue = new version_queue($iVersionId);
}
function create()
{
$bSuccess = TRUE;
/* Create a new vendor if an existing one was not selected, and
assign the application to it */
if(!$this->oApp->iVendorId)
{
$this->oVendor->create();
$this->oApp->iVendorId = $this->oVendor->iVendorId;
}
if(!$this->oApp->create())
$bSuccess = FALSE;
/* Assign the version to the new application */
$this->oVersionQueue->oVersion->iAppId = $this->oApp->iAppId;
if(!$this->oVersionQueue->create())
$bSuccess = FALSE;
return $bSuccess;
}
function update()
{
$bSuccess = TRUE;
/* If the vendor was already un-queued then the edit vendor form would not
have been displayed, and so the vendor name will not be set. Thus only
update the vendor if the name is set */
if($this->oVendor->sName)
$this->oVendor->update();
if(!$this->oApp->update())
$bSuccess = FALSE;
if(!$this->oVersionQueue->update())
$bSuccess = FALSE;
return $bSuccess;
}
function unQueue()
{
/* The vendor is not necessarily queued, as it could have existed on
beforehand */
if($this->oVendor->objectGetState() != 'accepted')
$this->oVendor->unQueue();
$this->oApp->unQueue();
$this->oVersionQueue->unQueue();
/* Has anyone submitted new versions while the app was queued?
If so we need to change their state from pending to queued */
$aOtherVersions = $this->oApp->objectGetChildrenClassSpecific('version');
foreach($aOtherVersions as $oVersion)
{
if($oVersion->objectGetState() == 'pending')
{
$oVersion->objectSetState('queued');
$oVersion->update();
}
}
}
function reQueue()
{
$this->oApp->reQueue();
$this->oVersionQueue->reQueue();
}
function reject()
{
$this->oVersionQueue->reject();
$this->oApp->reject();
}
function purge()
{
$bSuccess = TRUE;
if(!$this->oApp->purge())
$bSuccess = FALSE;
/* When deleting a duplicate app in the application queue, the version is moved
to another app and so when application_queue::delete() is called there is
no version child to delete, so check if the versionId is valid */
if($this->oVersionQueue->oVersion->iVersionId)
{
if(!$this->oVersionQueue->purge())
$bSuccess = FALSE;
}
return $bSuccess;
}
function delete()
{
$bSuccess = TRUE;
if(!$this->oApp->delete())
$bSuccess = FALSE;
/* When deleting a duplicate app in the application queue, the version is moved
to another app and so when application_queue::delete() is called there is
no version child to delete, so check if the versionId is valid */
if($this->oVersionQueue->oVersion->iVersionId)
{
if(!$this->oVersionQueue->delete())
$bSuccess = FALSE;
}
return $bSuccess;
}
function objectGetChildren($bIncludeDeleted = false)
{
return $this->oApp->objectGetChildren($bIncludeDeleted);
}
function objectGetSubmitterId()
{
return $this->oApp->objectGetSubmitterId();
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return $this->oApp->objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction);
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
return $this->oApp->objectGetMail($sAction, $bMailSubmitter, $bParentAction);
}
public function objectShowPreview()
{
if($this->oApp->sName)
return TRUE;
return FALSE;
}
function outputEditor($aClean = array())
{
/* We ask the user for the application name first so as to avoid duplicate
submissons; a list of potential duplicates is displayed on the next page */
if(!$this->oApp->sName)
{
echo "<div style='margin:auto; width: 500px; border:1px solid; background-color:#eee; padding:2px; '>\n";
echo "<div style='font-weight:bold; padding:3px;'>\n";
echo "Application name:\n";
echo "</div>\n";
echo "<div style='padding:5px;'>\n";
echo "<center><input type=\"text\" name=\"sAppName\" style='width:485px;'></center>\n";
echo "</div>\n";
echo "<input type=\"hidden\" name=\"sSub\" value=\"view\">\n";
echo "<input type=\"hidden\" name=\"sAppType\" value=\"application\">\n";
echo "</div>\n";
} else
{
/* Show potential duplicates */
echo html_frame_start("Potential duplicate applications in the ".
"database","90%","",0);
$this->displayDuplicates();
echo html_frame_end("&nbsp;");
$this->oApp->outputEditor();
/* Display the new vendor form for new applications or if we
are processing an application and the vendor is queued */
if(!$this->oApp->iAppId || $this->oVendor->objectGetState() != 'accepted')
{
echo html_frame_start("New Developer", "90%");
$this->oVendor->outputEditor();
echo html_frame_end();
}
$this->oVersionQueue->oVersion->outputEditor();
global $aClean;
echo $this->oVersionQueue->oDownloadUrl->outputEditorSingle(
$this->oVersionQueue->oVersion->iVersionId, $aClean);
$this->oVersionQueue->oTestDataQueue->outputEditor();
/* Allow the user to choose whether to preview the application view
or the version view. Application view is default */
echo html_frame_start("Select What to Preview");
$sPreviewVersion = $aClean['bPreviewVersion'] ? $aClean['bPreviewVersion'] : "";
$shPreviewApp = '';
$shPreviewVersion = '';
if($sPreviewVersion == "true")
$shPreviewVersion = ' checked="checked"';
else
$shPreviewApp = ' checked="checked"';
echo "<input type=\"radio\" name=\"bPreviewVersion\"$shPreviewApp value=\"false\"> Preview application<br>\n";
echo "<input type=\"radio\" name=\"bPreviewVersion\"$shPreviewVersion value=\"true\"> Preview version\n";
echo html_frame_end();
}
}
function getOutputEditorValues($aClean)
{
$this->oApp->getOutputEditorValues($aClean);
$this->oVersionQueue->getOutputEditorValues($aClean);
$this->oVendor->getOutputEditorValues($aClean);
}
function checkOutputEditorInput($aClean)
{
/* We want outputEditor() to be called again so we can display the main
app form. No erros are displayed since we only return TRUE */
if($this->oApp->sName && !$aClean['bMainAppForm'])
return TRUE;
$sErrors = $this->oApp->checkOutputEditorInput($aClean);
$sErrors .= $this->oVersionQueue->checkOutputEditorInput($aClean);
return $sErrors;
}
function objectGetState()
{
return $this->oApp->objectGetState();
}
function canEdit()
{
return $this->oApp->canEdit();
}
function mustBeQueued()
{
return $this->oApp->mustBeQueued();
}
function displayDuplicates()
{
echo "<b>Like matches</b><br />\n";
$this->displayDuplicateTable(searchForApplication($this->oApp->sName, $this->oApp->objectGetId()));
echo "<br />\n";
echo "<b>Partial matches</b><br />\n";
$this->displayDuplicateTable(searchForApplicationPartial($this->oApp->sName, $this->oApp->objectGetId()));
}
function displayDuplicateTable($hResult)
{
/* Exit if the MySQL handle is invalid */
if($hResult === FALSE)
return FALSE;
/* There's no point in displaying an empty table */
if($hResult === null || (query_num_rows($hResult) == 0))
{
echo "No matches.<br>\n";
return;
}
$aHeader = array(
"Application name",
"Description",
"No. versions"
);
/* We can only move data if the current application already exists, and
we have admin privileges */
if($this->oApp->iAppId && $_SESSION['current']->hasPriv("admin"))
{
$bCanMove = TRUE;
$aHeader[] = array("Move data", 'width="80"');
} else
{
$bCanMove = FALSE;
}
echo "<table cellpadding='5px'>";
echo html_tr($aHeader, "color4");
for($i = 0; $oRow = query_fetch_object($hResult); $i++)
{
$oApp = new application($oRow->appId);
$aCells = array(
$oApp->objectMakeLink(),
util_trim_description($oApp->sDescription),
sizeof($oApp->aVersionsIds)
);
if($bCanMove)
{
$aCells[] = "<a href=\"objectManager.php?sClass=application_queue&amp;".
"bIsQueue=true&amp;sAction=moveChildren&amp;iId=".
$this->oApp->iAppId."&amp;iNewId=".$oApp->iAppId.
"\">Move data</a>";
}
echo html_tr($aCells, ($i % 2) ? "color0" : "color1");
}
echo "</table>";
}
function objectGetCustomVars($sAction)
{
switch($sAction)
{
case "preview":
return array("bPreviewVersion");
default:
return 0;
}
}
function display($aClean = array())
{
/* Cache the version object if it is not in the database */
if(!$this->oVersionQueue->objectGetId())
$this->oApp->aVersions = array($this->oVersionQueue->oVersion);
$sPreviewVersion = $aClean['bPreviewVersion'] ? $aClean['bPreviewVersion'] : "";
if($sPreviewVersion == "true")
{
$this->oVersionQueue->oVersion->oApp = $this->oApp;
$this->oVersionQueue->display();
} else
{
$this->oApp->display();
}
}
function objectMakeUrl()
{
return $this->oApp->objectMakeUrl();
}
function objectMakeLink()
{
return $this->oApp->objectMakeLink();
}
function objectGetItemsPerPage($sState = 'accepted')
{
return $this->oApp->objectGetItemsPerPage($sState);
}
function objectGetEntriesCount($sState)
{
return $this->oApp->objectGetEntriesCount($sState);
}
public static function objectGetDefaultSort()
{
return application::objectGetDefaultSort();
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "appId", $bAscending = TRUE)
{
return $this->oApp->objectGetEntries($sState, $iRows, $iStart,
$sOrderBy, $bAscending);
}
public static function objectGetSortableFields()
{
return application::objectGetSortableFields();
}
function objectGetHeader($sState)
{
return $this->oApp->objectGetHeader($sState);
}
function objectGetTableRow()
{
return $this->oApp->objectGetTableRow();
}
function objectMoveChildren($iNewId)
{
return $this->oApp->objectMoveChildren($iNewId);
}
function objectDisplayQueueProcessingHelp()
{
return application::objectDisplayQueueProcessingHelp();
}
function objectDisplayAddItemHelp()
{
$this->oApp->objectDisplayAddItemHelp();
}
function allowAnonymousSubmissions()
{
return application::allowAnonymousSubmissions();
}
function objectAllowPurgingRejected()
{
return $this->oApp->objectAllowPurgingRejected();
}
public function objectGetSubmitTime()
{
return $this->oApp->objectGetSubmitTime();
}
function objectGetId()
{
return $this->oApp->objectGetId();
}
}
?>

686
include/bugs.php Normal file
View File

@@ -0,0 +1,686 @@
<?php
require_once(BASE."include/util.php");
require_once(BASE."include/application.php");
/******************************************/
/* bug class and related functions */
/******************************************/
/**
* Bug Link class for handling Bug Links and thumbnails
*/
class Bug
{
var $iLinkId;
// parameters necessary to create a new Bug with Bug::create()
var $iVersionId;
var $iBug_id;
// values retrieved from bugzilla
var $sShort_desc;
var $sBug_status;
var $sResolution;
var $sSubmitTime;
var $iSubmitterId;
var $bQueued;
/**
* Constructor, fetches the data and bug objects if $ilinkId is given.
*/
function bug($iLinkId = null, $oRow = null)
{
if(!$iLinkId && !$oRow)
return;
if(!$oRow)
{
$sQuery = "SELECT * FROM buglinks
WHERE linkId = '?'";
if($hResult = query_parameters($sQuery, $iLinkId))
{
$oRow = query_fetch_object($hResult);
}
}
if($oRow)
{
$this->iLinkId = $oRow->linkId;
$this->iBug_id = $oRow->bug_id;
$this->iVersionId = $oRow->versionId;
$this->bQueued = ($oRow->state=='queued') ? true : false;
$this->sSubmitTime = $oRow->submitTime;
$this->iSubmitterId = $oRow->submitterId;
/* lets fill in some blanks */
if ($this->iBug_id)
{
$sQuery = "SELECT *
FROM bugs
WHERE bug_id = ".$this->iBug_id;
if($hResult = query_bugzilladb($sQuery))
{
$oRow = query_fetch_object($hResult);
if($oRow)
{
$this->sShort_desc = $oRow->short_desc;
$this->sBug_status = $oRow->bug_status;
$this->sResolution = $oRow->resolution;
}
}
}
}
}
/**
* Creates a new Bug.
*/
function create()
{
$oVersion = new Version($this->iVersionId);
// Security, if we are not an administrator or a maintainer,
// the Bug must be queued.
if($this->mustBeQueued())
{
$this->bQueued = true;
} else
{
$this->bQueued = false;
}
/* lets check for a valid bug id */
if(!is_numeric($this->iBug_id))
{
addmsg($this->iBug_id." is not a valid bug number.", "red");
return false;
}
/* check that bug # exists in bugzilla*/
$sQuery = "SELECT *
FROM bugs
WHERE bug_id = ".$this->iBug_id;
if(query_num_rows(query_bugzilladb($sQuery, "checking bugzilla")) == 0)
{
addmsg("There is no bug in Bugzilla with that bug number.", "red");
return false;
}
/* Check for duplicates */
if($this->isDuplicate())
{
addmsg("The Bug link has already been submitted.", "red");
return false;
}
/* passed the checks so lets insert the puppy! */
$hResult = query_parameters("INSERT INTO buglinks (versionId, bug_id, ".
"submitTime, submitterId, state) ".
"VALUES('?', '?', ?, '?', '?')",
$this->iVersionId, $this->iBug_id,
"NOW()",
$_SESSION['current']->iUserId,
$this->bQueued ? 'queued' : 'accepted');
if($hResult)
{
$this->iLinkId = query_appdb_insert_id();
$this->SendNotificationMail();
return true;
} else
{
addmsg("Error while creating a new Bug link.", "red");
return false;
}
}
function purge()
{
return $this->delete();
}
/**
* Deletes the Bug from the database.
* and request its deletion from the filesystem (including the thumbnail).
*
* Return true if successful, false if an error occurs
*/
function delete()
{
$sQuery = "DELETE FROM buglinks
WHERE linkId = '?'";
if(!($hResult = query_parameters($sQuery, $this->iLinkId)))
return false;
return true;
}
/**
* Move Bug out of the queue.
*/
function unQueue()
{
// If we are not in the queue, we can't move the Bug out of the queue.
if(!$this->bQueued)
return false;
if(query_parameters("UPDATE buglinks SET state = '?' WHERE linkId='?'",
'accepted', $this->iLinkId))
{
$this->bQueued = false;
// we send an e-mail to interested people
$this->mailSubmitter();
$this->SendNotificationMail();
// the Bug has been unqueued
addmsg("The Bug has been unqueued.", "green");
}
}
function update()
{
$oBug = new bug($this->iLinkId);
// There is no need to have two links to a bug. The update is still
// considered successful
if($this->isDuplicate())
return $this->delete();
if($this->iVersionId && $this->iVersionId != $oBug->iVersionId)
{
$hResult = query_parameters("UPDATE buglinks SET versionId = '?'
WHERE linkId = '?'",
$this->iVersionId, $this->iLinkId);
if(!$hResult)
return false;
}
return true;
}
/* Checks whether the version already has a link for this bug */
public function isDuplicate()
{
$sQuery = "SELECT COUNT(linkId) as count
FROM buglinks
WHERE versionId = '?'
AND bug_id = '?'";
if($hResult = query_parameters($sQuery, $this->iVersionId, $this->iBug_id))
{
if(($oRow = query_fetch_object($hResult)))
{
return $oRow->count > 0;
}
}
return false;
}
function mailSubmitter($bRejected=false)
{
global $aClean;
if(!isset($aClean['sReplyText']))
$aClean['sReplyText'] = "";
if($this->iSubmitterId)
{
$oSubmitter = new User($this->iSubmitterId);
$sAppName = Version::fullName($this->iVersionId);
if(!$bRejected)
{
$sSubject = "Submitted Bug Link accepted";
$sMsg = "The bug link you submitted between Bug ".$this->iBug_id." and ".
$sAppName." has been accepted.";
} else
{
$sSubject = "Submitted Bug Link rejected";
$sMsg = "The bug link you submitted between Bug ".$this->iBug_id." and ".
$sAppName." has been deleted.";
}
$sMsg .= $aClean['sReplyText']."\n";
$sMsg .= "We appreciate your help in making the Application Database better for all users.";
mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg);
}
}
function SendNotificationMail($bDeleted=false)
{
$sAppName = version::fullName($this->iVersionId);
$oVersion = new version($this->iVersionId);
//show the application version URL and the bug URL
$sMsg = $oVersion->objectMakeUrl()."\n\n";
$sMsg .= BUGZILLA_ROOT."show_bug.cgi?id=".$this->iBug_id."\n";
if(!$bDeleted)
{
if(!$this->bQueued)
{
$sSubject = "Link between Bug ".$this->iBug_id." and ".$sAppName." added by ".$_SESSION['current']->sRealname;
if($this->iSubmitterId)
{
$oSubmitter = new User($this->iSubmitterId);
$sMsg .= "This Bug Link has been submitted by ".$oSubmitter->sRealname.".\n";
}
addmsg("The Bug Link was successfully added into the database.", "green");
} else // Bug Link queued.
{
$sSubject = "Link between Bug ".$this->iBug_id." and ".$sAppName." submitted by ".$_SESSION['current']->sRealname;
$sMsg .= "This Bug Link has been queued.\n";
addmsg("The Bug Link you submitted will be added to the database after being reviewed.", "green");
}
} else // Bug Link deleted.
{
$sSubject = "Link between Bug ".$this->iBug_id." and ".$sAppName." deleted by ".$_SESSION['current']->sRealname;
addmsg("Bug Link deleted.", "green");
}
$sEmail = User::get_notify_email_address_list(null, $this->iVersionId);
if($sEmail)
{
mail_appdb($sEmail, $sSubject ,$sMsg);
}
}
function objectGetSubmitterId()
{
return $this->iSubmitterId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
/* We don't do this at the moment */
return array(null, null, null);
}
public function objectGetParent($sClass = '')
{
return new version($this->iVersionId);
}
public function objectSetParent($iNewId, $sClass = '')
{
$this->iVersionId = $iNewId;
}
function objectGetChildren($bIncludeDeleted = false)
{
return array();
}
/* Get a list of bugs submitted by a given user */
function listSubmittedBy($iUserId, $bQueued = true)
{
$hResult = query_parameters("SELECT appFamily.appName, buglinks.versionId, appVersion.versionName, buglinks.submitTime, buglinks.bug_id, buglinks.linkId FROM buglinks, appFamily, appVersion WHERE appFamily.appId = appVersion.appId AND buglinks.versionId = appVersion.versionId AND buglinks.state = '?' AND buglinks.submitterId = '?' ORDER BY buglinks.versionId", $bQueued ? 'queued' : 'accepted', $iUserId);
if(!$hResult || !query_num_rows($hResult))
return FALSE;
$oTable = new Table();
$oTable->SetWidth("100%");
$oTable->SetAlign("center");
// setup the table header
$oTableRow = new TableRow();
$oTableRow->AddTextCell('Version');
$oTableRow->AddTextCell('Bug #', 'width="50"');
$oTableRow->AddTextCell('Status', 'width="80"');
$oTableRow->AddTextCell('Resolution', 'width="110"');
$oTableRow->AddTextCell('Description', 'Submit time');
$oTableRow->AddTextCell('Submit time');
if($bQueued)
$oTableRow->addTextCell('Action');
$oTableRow->SetClass('color4');
$oTable->AddRow($oTableRow);
for($i = 1; $oRow = query_fetch_object($hResult); $i++)
{
$oTableRow = new TableRow();
$oTableRow->AddTextCell(version::fullNameLink($oRow->versionId));
$oTableRow->AddTextCell('<a href="'.BUGZILLA_ROOT.'show_bug.cgi?id='.$oRow->bug_id.'">'.$oRow->bug_id.'</a>');
$oTableRow->AddTextCell($oBug->sBug_status);
$oTableRow->AddTextCell($oBug->sResolution);
$oTableRow->AddTextCell($oBug->sShort_desc);
$oTableRow->AddTextCell(print_date(mysqldatetime_to_unixtimestamp($oRow->submitTime)));
if($bQueued)
{
$oM = new objectManager('bug');
$oM->setReturnTo(array_key_exists('REQUEST_URI', $_SERVER) ? $_SERVER['REQUEST_URI'] : "");
$shDeleteLink = '<a href="'.$oM->makeUrl('delete', $oRow->linkId, 'Delete entry').'">delete</a>';
$oTableRow->addTextCell(" [ $shDeleteLink ]");
}
$oTableRow->SetClass(($i % 2 ) ? 'color0' : 'color1');
$oTable->AddRow($oTableRow);
}
return $oTable->GetString();
}
function isOpen()
{
return ($this->sBug_status != 'RESOLVED' && $this->sBug_status != 'CLOSED');
}
function allowAnonymousSubmissions()
{
return false;
}
function mustBeQueued()
{
$oVersion = new version($this->iVersionId);
if($_SESSION['current']->hasPriv("admin") ||
$_SESSION['current']->isMaintainer($oVersion->iVersionId) ||
$_SESSION['current']->isSuperMaintainer($oVersion->iAppId))
{
return false;
}
return true;
}
function objectGetId()
{
return $this->iLinkId;
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true)
{
$sLimit = "";
/* Selecting 0 rows makes no sense, so we assume the user
wants to select all of them
after an offset given by iStart */
if(!$iRows)
$iRows = bug::objectGetEntriesCount($sState);
$sQuery = "select * from buglinks where state = '?' LIMIT ?, ?";
$hResult = query_parameters($sQuery, $sState, $iStart, $iRows);
return $hResult;
}
function objectGetEntriesCount($sState)
{
$sQuery = "select count(*) as cnt from buglinks where state = '?'";
$hResult = query_parameters($sQuery, $sState);
$oRow = mysql_fetch_object($hResult);
return $oRow->cnt;
}
function objectGetHeader()
{
$oTableRow = new TableRow();
$oTableRow->AddTextCell("Bug #");
$oTableCell = new TableCell("Status");
$oTableCell->SetAlign("center");
$oTableRow->AddCell($oTableCell);
$oTableRow->AddTextCell("Bug Description");
$oTableCell = new TableCell("Application Name");
$oTableCell->SetAlign("center");
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell("Application Description");
$oTableCell->SetAlign("center");
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell("Version");
$oTableCell->SetAlign("center");
$oTableRow->AddCell($oTableCell);
return $oTableRow;
}
// returns a table row
function objectGetTableRow()
{
$oTableRow = new TableRow();
$oVersion = new version($this->iVersionId);
$oApp = new application($oVersion->iAppId);
$oTableCell = new TableCell($this->iBug_id);
$oTableCell->SetAlign("center");
$oTableCell->SetCellLink(BUGZILLA_ROOT.'show_bug.cgi?id='.$this->iBug_id);
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell($this->sBug_status);
$oTableCell->SetAlign("center");
$oTableRow->AddCell($oTableCell);
$oTableRow->AddTextCell($this->sShort_desc);
$oTableRow->AddTextCell($oApp->objectMakeLink());
$oTableRow->AddTextCell(util_trim_description($oApp->sDescription));
$oTableRow->AddTextCell($oVersion->objectMakeLink());
$oOMTableRow = new OMTableRow($oTableRow);
// enable the deletion link, the objectManager will check
// for appropriate permissions before adding the link
$oOMTableRow->SetHasDeleteLink(true);
return $oOMTableRow;
}
function objectMakeUrl()
{
$oManager = new objectManager("bug", "View Bug");
return $oManager->makeUrl("view", $this->objectGetId());
}
function objectMakeLink()
{
$sLink = "<a href=\"".$this->objectMakeUrl()."\">".
$this->sShort_desc."</a>";
return $sLink;
}
function objectGetState()
{
return ($this->bQueued) ? 'queued' : 'accepted';
}
function canEdit()
{
if($_SESSION['current']->hasPriv("admin"))
{
return true;
} else if($this->iVersionId)
{
if(maintainer::isUserMaintainer($_SESSION['current'],
$this->iVersionId))
{
return true;
}
if($this->iSubmitterId == $_SESSION['current']->iUserId)
return true;
}
return false;
}
function objectGetItemsPerPage($sState = 'accepted')
{
$aItemsPerPage = array(25, 50, 100, 200);
$iDefaultPerPage = 25;
return array($aItemsPerPage, $iDefaultPerPage);
}
function display()
{
$oTable = new Table();
$oTable->SetAlign("center");
$oTable->SetClass("color0");
$oTable->SetCellPadding(2);
$oHeaderRow = $this->objectGetHeader();
$oHeaderRow->SetClass("color4");
$oTable->AddRow($oHeaderRow);
$oDataRow = $this->objectGetTableRow();
$oDataRow->GetTableRow()->SetClass("color0");
$oTable->AddRow($oDataRow);
echo $oTable->GetString();
}
function objectHideReject()
{
return TRUE;
}
// NOTE: we don't have any editing support for this entry at this time
// so output the entry and a field to identify the bug id
function outputEditor()
{
$this->display();
echo '<input type="hidden" name="iBuglinkId" value="'.$this->iBug_id.'">';
echo '<input type="hidden" name="iVersionId" value="'.$this->iVersionId.'">';
}
function getOutputEditorValues($aClean)
{
$this->iBug_id = $aClean['iBuglinkId'];
if($aClean['iVersionId'])
$this->iVersionId = $aClean['iVersionId'];
}
}
/*
* Bug Link functions that are not part of the class
*/
function view_version_bugs($iVersionId = null, $aBuglinkIds)
{
global $aClean;
$bCanEdit = FALSE;
$oVersion = new Version($iVersionId);
// Security, if we are an administrator or a maintainer, we can remove or ok links.
if(($_SESSION['current']->hasPriv("admin") ||
$_SESSION['current']->isMaintainer($oVersion->iVersionId) ||
$_SESSION['current']->isSuperMaintainer($oVersion->iAppId)))
{
$bCanEdit = TRUE;
}
//start format table
if($_SESSION['current']->isLoggedIn())
{
echo "<form method=post action='".APPDB_ROOT."objectManager.php'>\n";
}
echo html_frame_start("Known bugs","98%",'',0);
echo "<table width=\"100%\" border=\"0\" cellpadding=\"3\" cellspacing=\"1\">\n\n";
echo "<tr class=color4>\n";
echo " <td align=center width=\"80\">Bug #</td>\n";
echo " <td>Description</td>\n";
echo " <td align=center width=\"80\">Status</td>\n";
echo " <td align=center width=\"80\">Resolution</td>\n";
echo " <td align=center width=\"80\">Other apps affected</td>\n";
if($bCanEdit == true)
{
echo " <td align=center width=\"80\">Delete</td>\n";
echo " <td align=center width=\"80\">Checked</td>\n";
}
echo "</tr>\n\n";
$c = 0;
foreach($aBuglinkIds as $iBuglinkId)
{
$oBuglink = new Bug($iBuglinkId);
if (
(!isset($aClean['sAllBugs']) && $oBuglink->isOpen() )
||
isset($aClean['sAllBugs'])
)
{
// set row color
$bgcolor = ($c % 2 == 0) ? "color0" : "color1";
//display row
echo "<tr class=$bgcolor>\n";
echo "<td align=center><a href='".BUGZILLA_ROOT."show_bug.cgi?id=".$oBuglink->iBug_id."'>".$oBuglink->iBug_id."</a></td>\n";
echo "<td>".$oBuglink->sShort_desc."</td>\n";
echo "<td align=center>".$oBuglink->sBug_status."</td>","\n";
echo "<td align=center>".$oBuglink->sResolution."</td>","\n";
echo "<td align=center><a href='viewbugs.php?bug_id=".$oBuglink->iBug_id."'>View</a></td>\n";
if($bCanEdit == true)
{
$oM = new objectManager("bug");
$oM->setReturnTo($oVersion->objectMakeUrl());
echo "<td align=center>[<a href='".$oM->makeUrl("delete", $oBuglink->iLinkId)."&amp;sSubmit=delete'>delete</a>]</td>\n";
if ($oBuglink->bQueued)
{
echo "<td align=center>[<a href='".$oM->makeUrl("edit", $oBuglink->iLinkId)."&amp;sSubmit=Submit&amp;bIsQueue=true'>OK</a>]</td>\n";
} else
{
echo "<td align=center>Yes</td>\n";
}
}
echo "</tr>\n\n";
$c++;
}
}
if($_SESSION['current']->isLoggedIn())
{
echo '<input type="hidden" name="iVersionId" value="'.$iVersionId.'">',"\n";
echo '<tr class=color3><td align=center>',"\n";
$sBuglinkId = isset($aClean['buglinkId']) ? $aClean['buglinkId'] : '';
echo '<input type="text" name="iBuglinkId" value="'.$sBuglinkId.'" size="8"></td>',"\n";
echo '<input type="hidden" name="sSubmit" value="Submit">',"\n";
echo '<input type="hidden" name="sClass" value="bug">',"\n";
echo '<input type="hidden" name="sReturnTo" value="'.$oVersion->objectMakeUrl().'">',"\n";
echo '<td><input type="submit" name="sSub" value="Submit a new bug link."></td>',"\n";
echo '<td colspan=6></td></tr></form>',"\n";
}
echo '</table>',"\n";
// show only open link
if ( isset( $aClean['sAllBugs'] ) )
{
$sURL = str_replace( '&sAllBugs', '', $_SERVER['REQUEST_URI'] );
$sLink = '<a href="' . htmlentities($sURL) . '">Show open bugs</a>';
}
// show all link
else
{
$sURL = $_SERVER['REQUEST_URI'] . '&sAllBugs';
$sLink = '<a href="' . htmlentities($sURL) . '">Show all bugs</a>';
}
echo '<div style="text-align:right;">' . $sLink .'</div>';
echo html_frame_end();
}
?>

576
include/category.php Normal file
View File

@@ -0,0 +1,576 @@
<?php
/***************************************************/
/* this class represents a category + its children */
/***************************************************/
/**
* Category class for handling categories.
*/
class Category {
var $iCatId;
var $iParentId;
var $sName;
var $sDescription;
var $aApplicationsIds; // an array that contains the appId of every application linked to this category
var $aSubcatsIds; // an array that contains the appId of every application linked to this category
/**
* constructor, fetches the data.
*/
function Category($iCatId = null)
{
// we are working on an existing category
if($iCatId=="0" || $iCatId)
{
/*
* We fetch the data related to this vendor.
*/
$sQuery = "SELECT *
FROM appCategory
WHERE catId = '?' ORDER BY catName;";
if($hResult = query_parameters($sQuery, $iCatId))
{
$oRow = query_fetch_object($hResult);
if($oRow)
{
$this->iCatId = $iCatId;
$this->iParentId = $oRow->catParent;
$this->sName = $oRow->catName;
$this->sDescription = $oRow->catDescription;
}
}
/*
* We fetch applicationsIds.
*/
$sQuery = "SELECT appId
FROM appFamily
WHERE catId = '?'
AND state = 'accepted' ORDER BY appName";
if($hResult = query_parameters($sQuery, $iCatId))
{
while($oRow = query_fetch_object($hResult))
{
$this->aApplicationsIds[] = $oRow->appId;
}
}
/*
* We fetch subcatIds.
*/
$sQuery = "SELECT catId
FROM appCategory
WHERE catParent = '?' ORDER BY catName;";
if($hResult = query_parameters($sQuery, $iCatId))
{
while($oRow = query_fetch_object($hResult))
{
$this->aSubcatsIds[] = $oRow->catId;
}
}
}
}
/**
* Creates a new category.
*/
function create()
{
$hResult = query_parameters("INSERT INTO appCategory (catName, catDescription, catParent) ".
"VALUES('?', '?', '?')",
$this->sName, $this->sDescription, $this->iParentId);
if($hResult)
{
$this->iCatId = query_appdb_insert_id();
$this->category($this->iCatId);
return true;
}
return false;
}
/**
* Update category.
* Returns true on success and false on failure.
*/
function update()
{
if(!query_parameters("UPDATE appCategory SET catName = '?', catDescription = '?', catParent = '?' WHERE catId = '?'",
$this->sName, $this->sDescription, $this->iParentId, $this->iCatId))
return false;
return true;
}
/**
* Deletes the category from the database.
*/
function delete()
{
if(!$this->canEdit())
return false;
if(sizeof($this->aApplicationsIds)>0)
return FALSE;
$sQuery = "DELETE FROM appCategory
WHERE catId = '?'
LIMIT 1";
query_parameters($sQuery, $this->iCatId);
return true;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetChildren()
{
/* We don't have any (or we do, sort of, but we don't use them for anything at the moment) */
return array();
}
/* Get a category's subcategory objects. Names are indented according
to subcategory level */
function getSubCatList($iLevel = 0)
{
$aOut = array();
$iId = $this->iCatId ? $this->iCatId : 0;
$sIndent = '';
for($i = 0; $i < $iLevel; $i++)
$sIndent .= '&nbsp; &nbsp;';
$hResult = query_parameters("SELECT * FROM appCategory WHERE catParent = '?'
ORDER BY catName", $iId);
while($oRow = mysql_fetch_object($hResult))
{
$oCat = new category($oRow->catId);
$oCat->sName = $sIndent.$oCat->sName;
$aOut[] = $oCat;
$aOut = array_merge($aOut, $oCat->getSubCatList($iLevel + 1));
}
return $aOut;
}
/* Get all category objects, ordered and with category names indented
according to subcategory level.
Optionally includes the 'Main' top category. */
static function getOrderedList($bIncludeMain = false)
{
$oCat = new category();
if(!$bIncludeMain)
return $oCat->getSubCatList(0);
$oCat->sName = 'Main';
$aCats = array($oCat);
$aCats = array_merge($aCats, $oCat->getSubCatList(1));
return $aCats;
}
/* Returns an SQL statement that will match items in the current category
and all sub-categories */
public function getSqlQueryPart()
{
$sRet = '';
$aSubCats = $this->getSubCatList();
$sRet .= " ( catId = '{$this->iCatId}' ";
foreach($aSubCats as $oCat)
{
$iCatId = $oCat->objectGetId();
$sRet .= " OR catId = '$iCatId' ";
}
$sRet .= ") ";
return $sRet;
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
/* We don't send notification mails */
return array(null, null, null);
}
/**
* returns a path like:
*
* { ROOT, Games, Simulation }
*/
function getCategoryPath()
{
$aPath = array();
$iCatId = $this->iCatId;
/* loop, working up through categories until we have no parent */
while($iCatId != 0)
{
$hResult = query_parameters("SELECT catName, catId, catParent FROM appCategory WHERE catId = '?'",
$iCatId);
if(!$hResult || query_num_rows($hResult) != 1)
break;
$oCatRow = query_fetch_object($hResult);
$aPath[] = array($oCatRow->catId, $oCatRow->catName);
$iCatId = $oCatRow->catParent;
}
$aPath[] = array(0, "ROOT");
return array_reverse($aPath);
}
/* return the total number of applications in this category */
function getApplicationCount($depth = null)
{
$MAX_DEPTH = 5;
if($depth)
$depth++;
else
$depth = 0;
/* if we've reached our max depth, just return 0 and stop recursing */
if($depth >= $MAX_DEPTH)
return 0;
$totalApps = 0;
/* add on all apps in each category this category includes */
if($this->aSubcatsIds)
{
while(list($i, $iSubcatId) = each($this->aSubcatsIds))
{
$subCat = new Category($iSubcatId);
$totalApps += $subCat->getApplicationCount($depth);
}
}
$totalApps += sizeof($this->aApplicationsIds); /* add on the apps at this category level */
return $totalApps;
}
/**
* create the Category: line at the top of appdb pages$
*/
function make_cat_path($aPath, $iAppId = '', $iVersionId = '')
{
$sStr = "";
$iCatCount = 0;
while(list($iCatIdx, list($iCatId, $sName)) = each($aPath))
{
if($sName == "ROOT")
$sCatname = "Main";
else
$sCatname = $sName;
if ($iCatCount > 0) $sStr .= " &gt; ";
$sStr .= html_ahref($sCatname,"objectManager.php?sClass=category&iId=$iCatId&sAction=view&sTitle=Browse+Applications");
$iCatCount++;
}
if($iAppId)
{
$oApp = new Application($iAppId);
if($iVersionId)
{
$oVersion = new Version($iVersionId);
$sStr .= " &gt; ".$oApp->objectMakeLink();
$sStr .= " &gt; ".$oVersion->sName;
} else
{
$sStr .= " &gt; ".$oApp->sName;
}
}
return $sStr;
}
public function objectGetState()
{
// We currenly don't queue categories
return 'accepted';
}
function objectGetId()
{
return $this->iCatId;
}
public function objectMakeLink()
{
return '<a href="'.$this->objectMakeUrl()."\">{$this->sName}</a>'";
}
public function objectMakeUrl()
{
return BASE."objectManager.php?sClass=category&sAction=view&iId={$this->iCatId}&sTitle=Browse+Applications";
}
public function objectAllowNullId($sAction)
{
switch($sAction)
{
case 'view':
return true;
default:
return false;
}
}
function objectGetSubmitterId()
{
/* We don't log that */
return 0;
}
function objectGetCustomVars($sAction)
{
switch($sAction)
{
case 'add':
return array('iParentId');
default:
return null;
}
}
function outputEditor($aValues = null)
{
$aCategories = category::getOrderedList(true);
$aCatNames = array();
$aCatIds = array();
$iParentId = $this->iParentId;
if(!$iParentId && $aValues)
$iParentId = getInput('iParentId', $aValues);
foreach($aCategories as $oCategory)
{
$aCatNames[] = $oCategory->sName;
$aCatIds[] = $oCategory->objectGetId();
}
echo "<table border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"2\">
<tr>
<td width=\"15%\" class=\"box-label\"><b>Category name</b></td>
<td class=\"box-body\">
<input type=\"text\" size=\"50\" name=\"sName\" value=\"".$this->sName."\">
</td>
</tr>
<tr>
<td width=\"15%\" class=\"box-label\"><b>Description</b></td>
<td class=\"box-body\">
<input type=\"text\" size=\"50\" name=\"sDescription\" value=\"".$this->sDescription."\">
</td>
</tr>
<tr>
<td width=\"15%\" class=\"box-label\"><b>Parent</b></td>
<td class=\"box-body\">
".html_select("iParentId",$aCatIds,$iParentId, $aCatNames)."
</td>
</tr>
</table>";
}
function allowAnonymousSubmissions()
{
return FALSE;
}
function getOutputEditorValues($aClean)
{
$this->sName = $aClean['sName'];
$this->iParentId = $aClean['iParentId'];
$this->sDescription = $aClean['sDescription'];
}
function mustBeQueued()
{
return $_SESSION['current']->hasPriv('admin');
}
function canEdit()
{
return $_SESSION['current']->hasPriv('admin');
}
/**
* display the full path of the Category we are looking at
*/
function displayPath($appId, $versionId = '')
{
$sCatFullPath = Category::make_cat_path($this->getCategoryPath(), $appId, $versionId);
echo html_frame_start("",'98%','',2);
echo "<p><b>Category: ". $sCatFullPath ."</b><br>\n";
echo html_frame_end();
}
public function display()
{
// list sub categories
$sCatFullPath = Category::make_cat_path($this->getCategoryPath());
$aSubs = $this->aSubcatsIds;
echo "<div class='default_container'>\n";
// Allow editing categories
if($this->canEdit())
{
$oM = new objectManager('category', '', $this->iCatId);
$oM->setReturnTo($this->objectMakeUrl());
echo "<p>\n";
echo '<a href="'.$oM->makeUrl('add', null, 'Add Category')."&iParentId={$this->iCatId}\">Add</a>";;
if($this->iCatId) // We can't edit the 'Main' category
{
echo ' &nbsp; &nbsp; ';
echo '<a href="'.$oM->makeUrl('edit', $this->iCatId, 'Edit Category').'">Edit</a>';
echo ' &nbsp; &nbsp; ';
echo '<a href="'.$oM->makeUrl('delete', $this->iCatId, 'Delete Category').'">Delete</a>';
}
echo "</p>\n";
}
// Output sub-categories
if($aSubs)
{
echo html_frame_start("",'98%','',2);
echo "<p><b>Category: ". $sCatFullPath ."</b><br>\n";
echo html_frame_end();
echo html_frame_start("","98%","",0);
$oTable = new Table();
$oTable->SetWidth("100%");
$oTable->SetBorder(0);
$oTable->SetCellPadding(3);
$oTable->SetCellSpacing(1);
$oTableRow = new TableRow();
$oTableRow->SetClass("color4");
$oTableRow->AddTextCell("Sub Category");
$oTableRow->AddTextCell("Description");
$oTableRow->AddTextCell("No. Apps");
$oTable->SetHeader($oTableRow);
while(list($i,$iSubcatId) = each($aSubs))
{
$oSubCat= new Category($iSubcatId);
//set row color
$sColor = ($i % 2) ? "color0" : "color1";
$oTableRowHighlight = GetStandardRowHighlight($i);
$sUrl = $oSubCat->objectMakeUrl();
$oTableRowClick = new TableRowClick($sUrl);
$oTableRowClick->SetHighlight($oTableRowHighlight);
//get number of apps in this sub-category
$iAppcount = $oSubCat->getApplicationCount();
//format desc
$sDesc = substr(stripslashes($oSubCat->sDescription),0,70);
//display row
$oTableRow = new TableRow();
$oTableRow->SetClass($sColor);
$oTableRow->SetRowClick($oTableRowClick);
$oTableCell = new TableCell($oSubCat->sName);
$oTableCell->SetCellLink($sUrl);
$oTableRow->AddCell($oTableCell);
$oTableRow->AddTextCell("$sDesc &nbsp;");
$oTableRow->AddTextCell("$iAppcount &nbsp;");
$oTable->AddRow($oTableRow);
}
// output the table
echo $oTable->GetString();
echo html_frame_end( count($aSubs) . ' categories');
}
// list applications in this category
$aApps = $this->aApplicationsIds;
if($aApps)
{
echo html_frame_start("",'98%','',2);
echo "<p><b>Category: ". $sCatFullPath ."</b><br>\n";
echo html_frame_end();
echo html_frame_start("","98%","",0);
$oTable = new Table();
$oTable->SetWidth("100%");
$oTable->SetBorder(0);
$oTable->SetCellPadding(3);
$oTable->SetCellSpacing(1);
$oTableRow = new TableRow();
$oTableRow->SetClass("color4");
$oTableRow->AddTextCell("Application name");
$oTableRow->AddTextCell("Description");
$oTableRow->AddTextCell("No. Versions");
$oTable->SetHeader($oTableRow);
while(list($i, $iAppId) = each($aApps))
{
$oApp = new Application($iAppId);
//set row color
$sColor = ($i % 2) ? "color0" : "color1";
$oTableRowHighlight = GetStandardRowHighlight($i);
$sUrl = $oApp->objectMakeUrl();
$oTableRowClick = new TableRowClick($sUrl);
$oTableRowClick->SetHighlight($oTableRowHighlight);
//format desc
$sDesc = util_trim_description($oApp->sDescription);
//display row
$oTableRow = new TableRow();
$oTableRow->SetRowClick($oTableRowClick);
$oTableRow->SetClass($sColor);
$oTableRow->AddTextCell($oApp->objectMakeLink());
$oTableRow->AddTextCell("$sDesc &nbsp;");
$oTableRow->AddTextCell(sizeof($oApp->aVersionsIds));
$oTable->AddRow($oTableRow);
}
// output table
echo $oTable->GetString();
echo html_frame_end( count($aApps) . " applications in this category");
}
// Show a message if this category is empty
if(!$aApps && !$aSubs)
{
echo html_frame_start("",'98%','',2);
echo "<p><b>Category: ". $sCatFullPath ."</b><br>\n";
echo html_frame_end();
echo html_frame_start('','90%','',2);
echo 'This category has no sub-categories or applications';
echo html_frame_end();
}
}
}
?>

796
include/comment.php Normal file
View File

@@ -0,0 +1,796 @@
<?php
/***************************************/
/* comment class and related functions */
/***************************************/
require_once(BASE."include/user.php");
/**
* Comment class for handling comments
*/
class Comment {
var $iCommentId;
// variables necessary for creating a comment
var $iParentId;
var $sSubject;
var $sBody;
var $iVersionId;
var $iAppId;
var $sDateCreated;
var $sHostname;
var $oOwner;
/**
* Constructor.
* If $iCommentId is provided, fetches comment.
*/
function Comment($iCommentId = null, $oRow = null)
{
if(!$iCommentId && !$oRow)
return;
if(!$oRow)
{
$sQuery = "SELECT appComments.*, appVersion.appId AS appId
FROM appComments, appVersion
WHERE appComments.versionId = appVersion.versionId
AND commentId = '?'";
$hResult = query_parameters($sQuery, $iCommentId);
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iCommentId = $oRow->commentId;
$this->iParentId = $oRow->parentId;
$oVersion = new version($this->iVersionId);
$this->iAppId = $oVersion->iAppId;
$this->iVersionId = $oRow->versionId;
$this->sSubject = $oRow->subject;
$this->sBody = $oRow->body;
$this->sDateCreated = $oRow->time;
$this->sHostname = $oRow->hostname;
$this->oOwner = new User($oRow->userId);
}
}
/*
* Creates a new comment.
* Informs interested people about the creation.
* Returns true on success, false on failure
*/
function create()
{
$hResult = query_parameters("INSERT INTO appComments
(parentId, versionId, subject, ".
"body, userId, time, hostname)
VALUES ('?', '?', '?', '?', '?', ?, '?')",
$this->iParentId, $this->iVersionId,
$this->sSubject, $this->sBody,
$_SESSION['current']->iUserId,
"NOW()", get_remote());
if($hResult)
{
$this->comment(query_appdb_insert_id());
$sEmail = User::get_notify_email_address_list($this->iAppId, $this->iVersionId);
$sEmail .= $this->oOwner->sEmail." ";
// fetches e-mails from parent comments, all parents are notified that a
// comment was added to the thread
$iParentId = $this->iParentId;
while($iParentId)
{
$oParent = new Comment($iParentId);
$sEmail .= $oParent->oOwner->sEmail." ";
$iParentId = $oParent->iParentId;
}
if($sEmail)
{
$aEmailArray = explode(" ", $sEmail); /* break the long email string into parts by spaces */
$aEmailArray = array_unique($aEmailArray); /* remove duplicates */
/* build the single string of all emails up */
$sEmail = "";
foreach($aEmailArray as $key=>$value)
{
$sEmail.="$value ";
}
$sSubject = "Comment for '".Application::lookup_name($this->iAppId)." ".Version::lookup_name($this->iVersionId)."' added by ".$_SESSION['current']->sRealname;
$sMsg = "To reply to this email please use the link provided below.\n";
$sMsg .= "DO NOT reply via your email client as it will not reach the person who wrote the comment\n";
$sMsg .= $this->objectMakeUrl()."\n";
$sMsg .= "\n";
$sMsg .= "Subject: ".$this->sSubject."\r\n";
$sMsg .= "\n";
$sMsg .= $this->sBody."\r\n";
mail_appdb($sEmail, $sSubject ,$sMsg);
}
addmsg("Comment created.", "green");
return true;
}
else
{
addmsg("Error while creating a new comment", "red");
return false;
}
}
/**
* Update comment.
* FIXME: Informs interested people about the modification.
* Returns true on success and false on failure.
*/
function update($sSubject=null, $sBody=null, $iParentId=null, $iVersionId=null)
{
$oComment = new comment($this->iCommentId);
if(!$iVersionId && $this->iVersionId != $oComment->iVersionId)
$iVersionId = $this->iVersionId;
if(!$iParentId && $this->iParentId != $oComment->iParentId)
$iParentId = $this->iParentId;
if ($iParentId)
{
if (!query_parameters("UPDATE appComments SET parentId = '?' WHERE commentId = '?'",
$iParentId, $this->iCommentId))
return false;
$this->iParentId = $iParentId;
}
if ($iVersionId)
{
if (!query_parameters("UPDATE appComments SET versionId = '?' WHERE commentId = '?'",
$iVersionId, $this->iCommentId))
return false;
$this->iVersionId = $iVersionId;
// FIXME: we need to refetch $this->iAppId.
}
if ($sSubject)
{
if (!query_parameters("UPDATE appComments SET subject = '?' WHERE commentId = '?'",
$sSubject, $this->iCommentId))
return false;
$this->sSubject = $sSubject;
}
if ($sBody)
{
if (!query_parameters("UPDATE appComments SET body = '?' WHERE commentId = '?'",
$sBody, $this->iCommentId))
return false;
$this->sBody = $sBody;
}
return true;
}
function purge()
{
return $this->delete();
}
/**
* Removes the current comment from the database.
* Informs interested people about the deletion.
* Returns true on success and false on failure.
*/
function delete()
{
$hResult = query_parameters("DELETE FROM appComments WHERE commentId = '?'", $this->iCommentId);
if ($hResult)
{
$aChildren = $this->objectGetChildren();
foreach($aChildren as $oComment)
$oComment->delete();
return true;
}
return false;
}
function get_comment_count_for_versionid($iVersionId)
{
$sQuery = "SELECT count(*) as cnt from appComments where versionId = '?'";
$hResult = query_parameters($sQuery, $iVersionId);
if(!$hResult) return 0;
$oRow = query_fetch_object($hResult);
return $oRow->cnt;
}
function getOutputEditorValues($aClean)
{
$this->sSubject = $aClean['sSubject'];
$this->sBody = $aClean['sBody'];
$this->iParentId = $aClean['iThread'];
if($aClean['iVersionId'])
$this->iVersionId = $aClean['iVersionId'];
if(!$this->oOwner)
$this->oOwner = $_SESSION['current'];
if(!$this->sDateCreated)
$this->sDateCreated = date("l F jS Y, H:i");
}
/**
* Displays the body of one comment.
*/
function view_comment_body($iCommentId)
{
$hResult = Comment::grab_comment($iCommentId);
if ($hResult)
{
$oRow = query_fetch_object($hResult);
Comment::view_app_comment($oRow);
}
}
/**
* display a single comment (in $oRow)
*/
function view_app_comment($oRow, $bShowAppName = false)
{
$oComment = new comment(null, $oRow);
$oComment->output_comment($bShowAppName);
}
private function output_comment($bShowAppName = false)
{
echo html_frame_start('','98%');
echo '<table width="100%" border="0" cellpadding="2" cellspacing="1">',"\n";
// message header
echo "<tr bgcolor=\"#E0E0E0\"><td><a name=Comment-".$this->iCommentId."></a>\n";
echo " <b>".$this->sSubject."</b><br>\n";
if($bShowAppName)
echo 'Application: ' . version::fullNameLink($this->iVersionId) . "<br>\n";
echo " by ".forum_lookup_user($this->oOwner->iUserId)." on ".$this->sDateCreated."<br>\n";
echo "</td></tr><tr><td>\n";
// body
echo htmlify_urls($this->sBody), "<br><br>\n";
$oVersion = new version($this->iVersionId);
$oM = new objectManager("comment", "Post new comment");
$oM->setReturnTo($oVersion->objectMakeUrl());
// reply post buttons
echo " [<a href=\"".$oM->makeUrl("add")."&iVersionId=$this->iVersionId\"><small>post new</small></a>] \n";
echo " [<a href=\"".$oM->makeUrl("add")."&iVersionId=$this->iVersionId".
"&iThread=$this->iCommentId\"><small>reply to this</small></a>] \n";
echo "</td></tr>\n";
// delete message button, for admins
if ($this->canEdit())
{
echo "<tr>";
echo "<td><form method=\"post\" name=\"sMessage\" action=\"".BASE."objectManager.php\"><input type=\"submit\" value=\"Delete\" class=\"button\">\n";
echo "<input type=\"hidden\" name=\"iId\" value=\"$this->iCommentId\">";
echo "<input type=\"hidden\" name=\"sClass\" value=\"comment\">";
echo "<input type=\"hidden\" name=\"bQueued\" value=\"false\">";
echo "<input type=\"hidden\" name=\"sAction\" value=\"delete\">";
echo "<input type=\"hidden\" name=\"sTitle\" value=\"Delete comment\">";
echo "<input type=\"hidden\" name=\"sReturnTo\" value=\"".$oVersion->objectMakeUrl()."\">";
echo "</form>\n";
echo "</td></tr>";
}
echo "</table>\n";
echo html_frame_end();
}
function display()
{
$this->output_comment();
}
/**
* grab single comment for commentId
*/
function grab_comment($iCommentId)
{
$iCommentId = query_escape_string($iCommentId);
if($iCommentId)
{
$sQuery = "SELECT from_unixtime(unix_timestamp(appComments.time), \"%W %M %D %Y, %k:%i\") as time, ".
"appComments.commentId, appComments.parentId, appComments.versionId, appComments.userId, appComments.subject, appComments.body, appVersion.appId ".
"FROM appComments, appVersion WHERE appComments.commentId = '$iCommentId'";
$hResult = query_appdb($sQuery);
return $hResult;
}
return null;
}
/**
* grab comments for appId / versionId
* if parentId is not -1 only comments for that thread are returned
*/
function grab_comments($iVersionId, $iParentId = null)
{
/* TODO: remove the logging when we figure out where the */
/* invalid $iVersionId is coming */
/* if $iVersionId is invalid we should log where we came from */
/* so we can debug the problem */
if($iVersionId == "")
{
error_log::logBackTrace("logging iVersionId oddity");
return NULL;
}
/* escape input so we can use query_appdb() without concern */
$iVersionId = query_escape_string($iVersionId);
$iParentId = query_escape_string($iParentId);
/* NOTE: we must compare against NULL here because $iParentId of 0 is valid */
if($iParentId)
{
$sExtra = "AND parentId = '".$iParentId."' ";
$sOrderingMode = "ASC";
} else
{
$sExtra = "AND parentId = '0'";
$sOrderingMode = "DESC";
}
$sQuery = "SELECT from_unixtime(unix_timestamp(appComments.time), \"%W %M %D %Y, %k:%i\") as time, ".
"appComments.commentId, appComments.parentId, appComments.versionId, appComments.userId, appComments.subject, appComments.body, appVersion.appId ".
"FROM appComments, appVersion WHERE appComments.versionId = appVersion.versionId AND appComments.versionId = '".$iVersionId."' ".
$sExtra.
"ORDER BY appComments.time $sOrderingMode";
$hResult = query_appdb($sQuery);
return $hResult;
}
/**
* display nested comments
* handle is a db result set
*/
function do_display_comments_nested($hResult)
{
while($oRow = query_fetch_object($hResult))
{
Comment::view_app_comment($oRow);
$hResult2 = Comment::grab_comments($oRow->versionId, $oRow->commentId);
if($hResult && query_num_rows($hResult2))
{
echo "<blockquote>\n";
Comment::do_display_comments_nested($hResult2);
echo "</blockquote>\n";
}
}
}
function display_comments_nested($versionId, $threadId)
{
$hResult = Comment::grab_comments($versionId, $threadId);
Comment::do_display_comments_nested($hResult);
}
/**
* Generates the link to show the comment.
*/
function comment_link($oRow)
{
$sLink = "commentview.php?iAppId={$oRow->appId}&iVersionId=".
"{$oRow->versionId}&iThreadId={$oRow->parentId}";
$sOnClick = "showComment('{$oRow->commentId}');";
/**
* The return false line in the onClick is used to handle javascript
* being disabled so we can fail gracefully to the old style.
*/
return "<li><a href=\"$sLink\" onclick=\"$sOnClick return false;\">$oRow->subject</a>".
' by '.forum_lookup_user($oRow->userId)." on
{$oRow->time}<div id=\"{$oRow->commentId}\"></div></li>\n";
}
/**
* display threaded comments
* handle is a db result set
*/
function do_display_comments_threaded($hResult, $is_main)
{
if (!$is_main)
echo "<ul>\n";
while ($oRow = query_fetch_object($hResult))
{
if ($is_main)
{
Comment::view_app_comment($oRow);
} else
{
$link = Comment::comment_link($oRow);
echo "$link";
}
$hResult2 = Comment::grab_comments($oRow->versionId, $oRow->commentId);
if ($hResult2 && query_num_rows($hResult2))
{
echo "<blockquote>\n";
Comment::do_display_comments_threaded($hResult2, 0);
echo "</blockquote>\n";
}
}
if (!$is_main)
echo "</ul>\n";
}
function canEdit()
{
if($_SESSION['current']->hasPriv("admin"))
return TRUE;
$oVersion = new version($this->iVersionId);
return $oVersion->canEdit();
}
function objectGetId()
{
return $this->iCommentId;
}
function objectGetSubmitterId()
{
return $this->oOwner->iUserId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
$oOptions = new mailOptions();
if($sAction == "delete" && $bParentAction)
$oOptions->bMailOnce = TRUE;
return $oOptions;
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
$sSubject = "";
$sMessage = "";
$aRecipients = null;
$oVersion = new version($this->iVersionId);
$sVerName = version::fullName($this->iVersionId);
if($bMailSubmitter)
{
switch($sAction)
{
case "delete":
if($bParentAction)
{
$sSubject = "Comments for $sVerName deleted";
$sMessage = "Your comments for $sVerName were deleted because the";
$sMessage .= "version was removed from the database";
} else
{
$sSubject = "Comment for $sVerName deleted";
$sMessage = $oVersion->objectMakeUrl()."\n";
$sMessage .= "\n";
$sMessage .= "This comment was made on ".substr($this->sDateCreated,0,10)."\n";
$sMessage .= "\n";
$sMessage .= "Subject: ".$this->sSubject."\r\n";
$sMessage .= "\n";
$sMessage .= $this->sBody."\r\n";
}
break;
}
} else
{
switch($sAction)
{
case "delete":
if(!$bParentAction)
{
$sSubject = "Comment for $sVerName deleted";
$sMessage = $oVersion->objectMakeUrl()."\n";
$sMessage .= "\n";
$sMessage .= "This comment was made on ".substr($this->sDateCreated,0,10)." by ".$this->oOwner->sRealname."\n";
$sMessage .= "\n";
$sMessage .= "Subject: ".$this->sSubject."\r\n";
$sMessage .= "\n";
$sMessage .= $this->sBody."\r\n";
}
break;
}
$aRecipients = User::get_notify_email_address_list($this->iAppId, $this->iVersionId);
}
return array($sSubject, $sMessage, $aRecipients);
}
public function objectGetParent($sClass = '')
{
switch($sClass)
{
case 'version':
return new version($this->iVersionId);
case 'comment':
return new comment($this->iParentId);
}
}
public function objectSetParent($iNewId, $sClass = '')
{
switch($sClass)
{
case 'version':
$this->iVersionId = $iNewId;
break;
case 'comment':
$this->iParentId = $iNewId;
break;
}
}
function objectGetChildren($bIncludeDeleted = false)
{
$aObjects = array();
$hResult = comment::grab_comments($this->iVersionId, $this->iCommentId);
if(!$hResult)
return $aObjects;
while($oRow = mysql_fetch_object($hResult))
{
$oComment = new comment(null, $oRow);
$aObjects += $oComment->objectGetChildren();
$aObjects[] = $oComment;
}
return $aObjects;
}
function display_comments_threaded($versionId, $threadId = 0)
{
$hResult = Comment::grab_comments($versionId, $threadId);
Comment::do_display_comments_threaded($hResult, 1);
}
/**
* display flat comments
*/
function display_comments_flat($versionId)
{
$hResult = Comment::grab_comments($versionId);
if ($hResult)
{
while($oRow = query_fetch_object($hResult))
{
Comment::view_app_comment($oRow);
}
}
}
function view_app_comments($versionId, $threadId = 0)
{
global $aClean;
// count posts
$hResult = query_parameters("SELECT commentId FROM appComments WHERE versionId = '?'", $versionId);
$messageCount = query_num_rows($hResult);
//start comment format table
echo html_frame_start("","98%",'',0);
echo '<table width="100%" border="0" cellpadding="1" cellspacing="0">',"\n";
echo '<tr><td bgcolor="#C0C0C0" align="center"><table border="0" cellpadding="0" cellspacing="0"><tr bgcolor="#C0C0C0">',"\n";
$oVersion = new version($versionId);
// message display mode changer
if ($_SESSION['current']->isLoggedIn())
{
// FIXME we need to change this so not logged in users can change current view as well
if (!empty($aClean['sCmode']))
$_SESSION['current']->setPref("comments:mode", $aClean['sCmode']);
$sel[$_SESSION['current']->getPref("comments:mode", "threaded")] = 'selected';
echo '<td><form method="post" name="sMode" action="'.
$oVersion->objectMakeUrl().'">',"\n";
echo "<b>Application comments:</b> $messageCount total comments ";
echo '<b>Mode:</b> <select name="sCmode" onchange="document.sMode.submit();">',"\n";
echo ' <option value="flat" '.$sel['flat'].'>Flat</option>',"\n";
echo ' <option value="threaded" '.$sel['threaded'].'>Threaded</option>',"\n";
echo ' <option value="nested" '.$sel['nested'].'>Nested</option>',"\n";
echo ' <option value="off" '.$sel['off'].'>No Comments</option>',"\n";
echo '</select>',"\n";
echo '</form></td>',"\n";
}
// blank space
echo '<td> &nbsp; </td>',"\n";
$oM = new objectManager("comment", "Add comment");
$oM->setReturnTo($oVersion->objectMakeUrl());
// post new message button
echo '<td><form method="post" name="sMessage" action="objectManager.php">';
echo '<input type="hidden" name="sAction" value="add">';
echo $oM->makeUrlFormData();
echo '<input type="submit" value="Post new comment" class="button"> ',"\n";
echo '<input type="hidden" name="iVersionId" value="'.$versionId.'"></form></td>',"\n";
//end comment format table
echo '</tr></table></td></tr>',"\n";
echo '</table>',"\n";
echo html_frame_end();
if( $messageCount > 0 )
{
echo '<p align="center">The following comments are owned by whoever posted them. WineHQ is not responsible for what they say.</p>'."\n";
}
//start comments
echo '<table width="100%" border="0" cellpadding="2" cellspacing="1"><tr><td>',"\n";
//hide or display depending on pref
if ($_SESSION['current']->isLoggedIn())
$mode = $_SESSION['current']->getPref("comments:mode", "threaded");
else
$mode = "threaded"; /* default non-logged in users to threaded comment display mode */
if ( isset($aClean['sMode']) && $aClean['sMode']=="nested")
$mode = "nested";
switch ($mode)
{
case "flat":
Comment::display_comments_flat($versionId);
break;
case "nested":
Comment::display_comments_nested($versionId, $threadId);
break;
case "threaded":
Comment::display_comments_threaded($versionId, $threadId);
break;
}
echo '</td></tr></table>',"\n";
}
function allowAnonymousSubmissions()
{
return FALSE;
}
function objectGetCustomVars($sAction)
{
switch($sAction)
{
case "add":
return array("iThread", "iVersionId");
default:
return null;
}
}
function checkOutputEditorInput($aClean)
{
$sErrors = "";
if(!$aClean['iVersionId'])
$sErrors .= "<li>No version id defined; something may have gone wrong with the URL</li>\n";
if(!$aClean['sBody'])
$sErrors .= "<li>You need to enter a message!</li>\n";
return $sErrors;
}
function outputEditor($aClean)
{
$sMesTitle = "<b>Post New Comment</b>";
if($aClean['iThread'] > 0)
{
$hResult = query_parameters("SELECT * FROM appComments WHERE commentId = '?'",
$aClean['iThread']);
$oRow = query_fetch_object($hResult);
if($oRow)
{
$sMesTitle = "<b>Replying To ...</b> $oRow->subject\n";
echo html_frame_start($oRow->subject,500);
echo htmlify_urls($oRow->body), "<br><br>\n";
echo html_frame_end();
/* Set default reply subject */
if(!$this->sSubject)
{
// Only add RE: once
if(eregi("RE:", $oRow->subject))
$this->sSubject = $oRow->subject;
else
$this->sSubject = "RE: ".$oRow->subject;
}
}
}
echo "<p align=\"center\">Enter your comment in the box below.";
echo "</br>Please do not paste large terminal or debug outputs here.</p>";
echo html_frame_start($sMesTitle,500,"",0);
echo '<table width="100%" border=0 cellpadding=0 cellspacing=1>',"\n";
echo "<tr class=\"color0\"><td align=right><b>From:</b>&nbsp;</td>\n";
echo " <td>&nbsp;".$_SESSION['current']->sRealname."</td></tr>\n";
echo "<tr class=\"color0\"><td align=right><b>Subject:</b>&nbsp;</td>\n";
echo " <td>&nbsp;<input type=\"text\" size=\"35\" name=\"sSubject\" value=\"".$this->sSubject."\"> </td></tr>\n";
echo "<tr class=\"color1\"><td colspan=2><textarea name=\"sBody\" cols=\"70\" rows=\"15\" wrap=\"virtual\">".$this->sBody."</textarea></td></tr>\n";
echo "</table>\n";
echo html_frame_end();
echo "<input type=\"hidden\" name=\"iThread\" value=\"".$aClean['iThread']."\">\n";
echo "<input type=\"hidden\" name=\"iVersionId\" value=\"".$aClean['iVersionId']."\">\n";
}
function objectShowPreview()
{
return TRUE;
}
function objectMakeUrl()
{
$oVersion = new version($this->iVersionId);
$sUrl = $oVersion->objectMakeUrl()."#Comment-".$this->iCommentId;
return $sUrl;
}
}
/*
* Comment functions that are not part of the class
*/
function forum_lookup_user($iUserId)
{
if ($iUserId > 0)
{
$oUser = new User($iUserId);
if($_SESSION['current']->isLoggedIn())
$sMailto = '<a href="'.BASE.'contact.php?iRecipientId='.
$oUser->iUserId.'">' .$oUser->sRealname . '</a>';
else
$sMailto = $oUser->sRealname;
}
if (!$iUserId || !$oUser->isLoggedIn())
{
$sMailto = 'Anonymous';
}
return $sMailto;
}
?>

57
include/config.php Normal file
View File

@@ -0,0 +1,57 @@
<?php
/*************************/
/* config file for AppDB */
/*************************/
/*
* global params
*/
define("APPDB_DEBUG","1"); //turns debugging on/off
define("APPDB_DONT_CLEAR_COOKIES_VAR","0"); // set to 1 if you have more than one Web application on the same virtual host
define("APPDB_THUMBNAIL_WIDTH","128"); // width of the screenshot's thumbnails
define("APPDB_THUMBNAIL_HEIGHT","128"); // height of the screenshot's thumbnails
define("APPDB_SCREENSHOT_MAXWIDTH","1600"); // width of the screenshot's thumbnails
define("APPDB_SCREENSHOT_MAXHEIGHT","1200"); // height of the screenshot's thumbnails
define("APPDB_ROOT", "http://www.claunia.com/qemu3/appdb/"); // path to AppDB
define("APPDB_OWNER","QEMU"); // with what product/company is this AppDB related ?
define("APPDB_OWNER_URL","http://www.claunia.com/"); // website of this product/company
define("APPDB_OWNER_EMAIL","natalia@claunia.com"); // e-mail of this product/company
define("APPDB_SENDER_EMAIL","appdb-noreply@claunia.com"); // The e-mail address which appears as the sender in mails sent by the AppDB
define("BUGZILLA_ROOT","http://bugs.claunia.com/"); // path to bugzilla
// AppDB developers: Use this define to disable email from being sent from the appdb during testing
//if(!defined("DISABLE_EMAIL"))
// define("DISABLE_EMAIL", true); // disable email, see mail_appdb() in include/mail.php
// AppDB developers: Use this define to print the contents of the e-mail instead
// of sending it, useful for testing e-mail notifications. Has no effect if
// DISABLE_EMAIL is set
//if(!defined("PRINT_EMAIL"))
// define("PRINT_EMAIL", true); // print email, see mail_appdb() in include/mail.php
// How old (days) a test report has to before it is judged to be aged
define("TESTDATA_AGED_THRESHOLD", 175);
// Show versions from these branches even if they are not among the most recent ones
// Separate by commas if there are more than one
define("STABLE_BRANCHES", "0.8.0, 0.9.0, 0.10.0, 0.11.0");
/*
* apps database info
*/
define("APPS_DBUSER","qemu");
define("APPS_DBPASS","nsVxeFyvarqnQXfj");
define("APPS_DBHOST","localhost");
define("APPS_DB","apidb");
/*
* bugzilla database info
*/
define("BUGZILLA_DBUSER","qemu");
define("BUGZILLA_DBPASS","nsVxeFyvarqnQXfj");
define("BUGZILLA_DBHOST","localhost");
define("BUGZILLA_DB","bugs");
define("BUGZILLA_PRODUCT_ID","1");
?>

57
include/config.php.sample Normal file
View File

@@ -0,0 +1,57 @@
<?php
/*************************/
/* config file for AppDB */
/*************************/
/*
* global params
*/
define("APPDB_DEBUG","0"); //turns debugging on/off
define("APPDB_DONT_CLEAR_COOKIES_VAR","0"); // set to 1 if you have more than one Web application on the same virtual host
define("APPDB_THUMBNAIL_WIDTH","128"); // width of the screenshot's thumbnails
define("APPDB_THUMBNAIL_HEIGHT","128"); // height of the screenshot's thumbnails
define("APPDB_SCREENSHOT_MAXWIDTH","1024"); // width of the screenshot's thumbnails
define("APPDB_SCREENSHOT_MAXHEIGHT","768"); // height of the screenshot's thumbnails
define("APPDB_ROOT", "http://localhost/appdb/"); // path to AppDB
define("APPDB_OWNER","WineHQ"); // with what product/company is this AppDB related ?
define("APPDB_OWNER_URL","http://www.winehq.org/"); // website of this product/company
define("APPDB_OWNER_EMAIL","appdb@winehq.org"); // e-mail of this product/company
define("APPDB_SENDER_EMAIL","appdb-noreply@winehq.org"); // The e-mail address which appears as the sender in mails sent by the AppDB
define("BUGZILLA_ROOT","http://bugs.winehq.org/"); // path to bugzilla
// AppDB developers: Use this define to disable email from being sent from the appdb during testing
//if(!defined("DISABLE_EMAIL"))
// define("DISABLE_EMAIL", true); // disable email, see mail_appdb() in include/mail.php
// AppDB developers: Use this define to print the contents of the e-mail instead
// of sending it, useful for testing e-mail notifications. Has no effect if
// DISABLE_EMAIL is set
//if(!defined("PRINT_EMAIL"))
// define("PRINT_EMAIL", true); // print email, see mail_appdb() in include/mail.php
// How old (days) a test report has to before it is judged to be aged
define("TESTDATA_AGED_THRESHOLD", 175);
// Show versions from these branches even if they are not among the most recent ones
// Separate by commas if there are more than one
define("STABLE_BRANCHES", "1.0.");
/*
* apps database info
*/
define("APPS_DBUSER","wineowner");
define("APPS_DBPASS","lemonade");
define("APPS_DBHOST","localhost");
define("APPS_DB","apidb");
/*
* bugzilla database info
*/
define("BUGZILLA_DBUSER","root");
define("BUGZILLA_DBPASS","");
define("BUGZILLA_DBHOST","localhost");
define("BUGZILLA_DB","bugs");
define("BUGZILLA_PRODUCT_ID","1");
?>

233
include/db_filter.php Normal file
View File

@@ -0,0 +1,233 @@
<?php
/**
* Classes for managing SQL filters (parts of SQL queries)
*
* Copyright 2008 BitSplash Software LLC
* Copyright 2008 Alexander N. Sørnes <alex@thehandofagony.com>
*
*/
define('FILTER_LIKE', 1);
define('FILTER_CONTAINS', 2); // Same as LIKE, but value is wrapped by wildcards
define('FILTER_STARTS_WITH', 3); // Same as LIKE, but with a prepended wildcard
define('FILTER_ENDS_WITH', 4); // Same as LIKE, but with an appended wildcard
define('FILTER_EQUALS', 5);
define('FILTER_GREATER_THAN', 6);
define('FILTER_LESS_THAN', 7);
define('FILTER_NOT_EQUALS', 8);
define('FILTER_NOT_LIKE', 9);
define('FILTER_OPTION_BOOL', 10);
define('FILTER_OPTION_ENUM', 11);
/* A filter as part of an SQL query, such as something = 'somevalue' */
class Filter
{
private $sColumn; // The table column the filter is for
private $iType; // The type of filter, like EQUALS, LIKE
private $sData; // What the column is to be compared to */
public function Filter($sColumn, $iType, $sData)
{
$this->sColumn = $sColumn;
$this->iType = $iType;
$this->sData = $sData;
}
public function getColumn()
{
return $this->sColumn;
}
public function setData($sData)
{
$this->sData = $sData;
}
public function getOperatorId()
{
return $this->iType;
}
public function getData()
{
return $this->sData;
}
public function getOperator()
{
switch($this->iType)
{
case FILTER_LIKE:
case FILTER_CONTAINS:
case FILTER_STARTS_WITH:
case FILTER_ENDS_WITH:
return 'LIKE';
case FILTER_EQUALS:
return '=';
case FILTER_LESS_THAN:
return '<';
case FILTER_GREATER_THAN:
return '>';
case FILTER_NOT_EQUALS:
return '!=';
case FILTER_NOT_LIKE:
return 'NOT LIKE';
default:
return 0; // error
}
}
/* Gets an SQL expression representing the current filter, for use in a WHERE clause */
public function getExpression()
{
/* We let callers handle options themselves, so don't include them in the WHERE clause */
if($this->isOption())
return '';
$sData = $this->sData;
/* Add wildcards if required */
switch($this->iType)
{
case FILTER_CONTAINS:
$sData = "%$sData%";
break;
case FILTER_STARTS_WITH:
$sData = "$sData%";
break;
case FILTER_ENDS_WITH:
$sData = "%$sData";
break;
}
$sOp = $this->getOperator();
return "{$this->sColumn} $sOp '$sData'";
}
public function IsOption()
{
switch($this->iType)
{
case FILTER_OPTION_BOOL:
case FILTER_OPTION_ENUM:
return true;
default:
return false;
}
}
}
/* Class handling tables where the user can filter contents */
class FilterSet
{
private $aFilters; // Array of filters for this table
public function FilterSet($sTableName = '')
{
$this->aFilters = array();
if($sTableName)
$this->loadTable($sTableName);
}
public function loadTable($sTableName)
{
$sQuery = "SELECT * FROM $sTableName";
$hResult = query_appdb($sQuery);
while($oRow = mysql_fetch_object($hResult))
{
$this->addFilterObject(new Filter($oRow->sColumn, $oRow->iType, $oRow->sData));
}
}
public function saveTable($sTableName)
{
$hResult = query_appdb("DROP TABLE IF EXISTS $sTableName");
$hResult = query_appdb("CREATE TABLE $sTableName (
sColumn VARCHAR(255) NOT NULL,
iType INT(3) NOT NULL,
sData VARCHAR(255) NOT NULL DEFAULT ''
)");
if(!$hResult)
return false;
$bSuccess = true;
foreach($this->aFilters as $oFilter)
{
$hResult = query_appdb("INSERT INTO $sTableName (sColumn,iType,sData)
VALUES('{$oFilter->getColumn()}','{$oFilter->getOperatorId()}','{$oFilter->getData()}')");
if(!$hResult)
$bSuccess = false;
}
return $bSuccess;
}
public function addFilterObject(Filter $oFilter)
{
$this->aFilters[] = $oFilter;
}
public function AddFilter($sColumn, $iType, $sData)
{
$this->aFilters[] = new Filter($sColumn, $iType, $sData);
}
public function getFilterCount()
{
return sizeof($this->aFilters);
}
public function getFilters()
{
return $this->aFilters;
}
public function getWhereClause()
{
$aFilters = array();
for($i = 0; $i < sizeof($this->aFilters); $i++)
{
$oFilter = $this->aFilters[$i];
$sThisFilter = $oFilter->getExpression();
if($sThisFilter)
$aFilters[] = $sThisFilter;
}
return implode($aFilters, ' AND ');
}
function getQuery($sTable, $iLimit = 0)
{
$sWhere = $this->getFilterCount() ? 'WHERE '.$this->getWhereClause() : '';
$sQuery = "SELECT * FROM $sTable $sWhere";
$iLimit = mysql_real_escape_string($iLimit);
if($iLimit)
$sQuery .= " LIMIT 0,$iLimit";
return $sQuery;
}
function getMatchedItems($sTable, $iLimit = 0)
{
return query_appdb($this->getQuery($sTable, $iLimit));
}
function getMatchedItemsCount($sTable)
{
return mysql_num_rows($this->getMatchedItems($sTable));
}
}
?>

567
include/db_filter_ui.php Normal file
View File

@@ -0,0 +1,567 @@
<?php
/**
* User interface for the SQL filter classes
*
* Copyright 2008 BitSplash Software LLC
* Copyright 2008 Alexander N. Sørnes <alex@thehandofagony.com>
*
*/
require_once('db_filter.php');
define('FILTER_VALUES_NORMAL', 1);
define('FILTER_VALUES_ENUM', 2);
define('FILTER_VALUES_OPTION_BOOL', 3);
define('FILTER_VALUES_OPTION_ENUM', 4);
define('MAX_FILTERS', 50);
/* Info describing an available filter: what column it applies to,
and what comparison options are available */
class FilterInfo
{
private $sColumn;
private $sDisplayName;
private $aTypes; // Available filters for this column
private $iValueType; // Normal, enum ...
private $aValueTypeData; // List of enums
private $aValueTypeDataDisplay; // Optional display names for enums
public function FilterInfo($sColumn, $sDisplayName, $aTypes, $iValueType = FILTER_VALUES_NORMAL, $aValueTypeData = array(), $aValueTypeDisplay = array())
{
$this->sColumn = $sColumn;
$this->sDisplayName = $sDisplayName;
$this->aTypes = $aTypes;
$this->iValueType = $iValueType;
$this->aValueTypeData = $aValueTypeData;
if(sizeof($aValueTypeData) && !sizeof($aValueTypeDisplay))
$this->aValueTypeDataDisplay = $aValueTypeData;
else
$this->aValueTypeDataDisplay = $aValueTypeDisplay;
}
public function getColumn()
{
return $this->sColumn;
}
public function getDisplayName()
{
return $this->sDisplayName;
}
public function getValueType()
{
return $this->iValueType;
}
public function getValueTypeData()
{
return $this->aValueTypeData;
}
public function getValueTypeDataDisplay()
{
return $this->aValueTypeDataDisplay;
}
public function getTypes()
{
return $this->aTypes;
}
public function isOption()
{
switch($this->iValueType)
{
case FILTER_VALUES_OPTION_BOOL:
case FILTER_VALUES_OPTION_ENUM:
return true;
default:
return false;
}
}
public static function getOpName($iOpId)
{
switch($iOpId)
{
case FILTER_EQUALS:
return 'equal to';
case FILTER_LIKE:
return 'like';
case FILTER_CONTAINS:
return 'contains';
case FILTER_STARTS_WITH:
return 'starts with';
case FILTER_ENDS_WITH:
return 'ends with';
case FILTER_NOT_LIKE:
return 'not like';
case FILTER_NOT_EQUALS:
return 'not equal to';
case FILTER_LESS_THAN:
return 'less than';
case FILTER_GREATER_THAN:
return 'greater than';
}
}
}
/* Class handling tables where the user can filter contents */
class FilterInterface
{
private $aFilterInfo;
private $oFilterSet;
private $aEscapeChars;
private $aEscapeCharsWith;
private $sErrors; // Used to inform the user about errors (and to give advice)
public function FilterInterface($sTableName = '')
{
$this->aFilterInfo = array();
$this->oFilterSet = new FilterSet(query_escape_string($sTableName));
$this->aEscapeChars = array('.');
$this->aEscapeCharsWith = array('-');
$this->sErrors = '';
}
public function AddFilterObject(Filter $oFilter)
{
$this->oFilterSet->AddFilterObject($oFilter);
}
public function setFilterSet(FilterSet $oSet)
{
$this->oFilterSet = $oSet;
}
/* Convenience function to add a filter option */
public function AddFilterInfo($sColumn, $sDisplayName, $aTypes, $iValueType = VALUE_TYPE_NORMAL, $aValueTypeData = array(), $aValueTypeDisplay = array())
{
$this->aFilterInfo[$sColumn] = new FilterInfo($sColumn, $sDisplayName, $aTypes, $iValueType, $aValueTypeData, $aValueTypeDisplay);
}
/* We can't use some special chars in variable names, such as '.' */
public function escapeChars($sIn)
{
return str_replace($this->aEscapeChars, $this->aEscapeCharsWith, $sIn);
}
public function unescapeChars($sIn)
{
return str_replace($this->aEscapeWith, $this->aEscape, $sIn);
}
public function getUrlElement($iId, Filter $oFilter)
{
$sColumn = $this->escapeChars($oFilter->getColumn());
$sId = $iId;
$shEditor = "&i{$sColumn}Op$sId={$oFilter->getOperatorId()}";
$shEditor .= "&s{$sColumn}Data$sId={$oFilter->getData()}";
return $shEditor;
}
public function getHiddenInputTag($iId, Filter $oFilter)
{
$sColumn = $this->escapeChars($oFilter->getColumn());
$sId = $iId;
$shEditor = "<input type=\"hidden\" name=\"i{$sColumn}Op$sId\" value=\"{$oFilter->getOperatorId()}\">";
$shEditor .= "<input type=\"hidden\" name=\"s{$sColumn}Data$sId\" value=\"{$oFilter->getData()}\" />";
return $shEditor;
}
public function getOptionBoolEditor($iId, Filter $oFilter)
{
$sColumn = $this->escapeChars($oFilter->getColumn());
$oColumn = $this->aFilterInfo[$oFilter->getColumn()];
$sId = ($iId == -1) ? '' : $iId;
$aTypes = $oColumn->getTypes();
$iOp = $aTypes[0];
if($iId == -1)
{
/* The first entry in the list of choices is the default */
$aValues = $oColumn->getValueTypeData();
$sData = $aValues[0];
} else
{
$sData = $oFilter->getData();
}
$shRet = "<input type=\"hidden\" name=\"i{$sColumn}Op$sId\" value=\"$iOp\" />";
if($sData == 'true')
$sChecked = ' checked="checked"';
else
$sChecked = '';
$shRet .= "<input value=\"true\" $sChecked name=\"s{$sColumn}Data$sId\" type=\"checkbox\" />";
$shRet .= ' '.$oColumn->getDisplayName();
return $shRet;
}
public function getItemEditor($iId, Filter $oFilter)
{
$sColumn = $this->escapeChars($oFilter->getColumn());
$oColumn = $this->aFilterInfo[$oFilter->getColumn()];
$sId = ($iId == -1) ? '' : $iId;
$shEditor = $oColumn->getDisplayName().' ';
$aTypes = $oColumn->getTypes();
/* It doesn't make sense to show a dropdown menu of choices if there is only one
If the filter is already active then there are more than one; one to remove */
if($iId == -1 && sizeof($aTypes) == 1)
{
echo "<input type=\"hidden\" name=\"i{$sColumn}Op$sId\" value=\"{$aTypes[0]}\" />";
/* Printing 'equal to' sounds weird if it is the only choice */
if($aTypes[0] != FILTER_EQUALS)
$shEditor .= $oColumn->getOpName($aTypes[0]);
} else if ($aTypes[0] != FILTER_OPTION_ENUM)
{
$shEditor .= "<select name='i{$sColumn}Op$sId'>";
if($iId != -1)
{
$sSel = '';
$sText = 'remove';
$shEditor .= "<option value='0'$sSel>-- $sText --</option>";
}
foreach($aTypes as $iType)
{
if($oFilter->getOperatorId() == $iType)
$sSel = " selected='selected'";
else
$sSel = '';
$shEditor .= "<option value='$iType'$sSel>".$oColumn->getOpName($iType).'</option><br />';
}
$shEditor .= '</select> ';
} else
{
echo "<input type=\"hidden\" name=\"i{$sColumn}Op$sId\" value=\"{$aTypes[0]}\" />";
}
switch($oColumn->getValueType())
{
case FILTER_VALUES_NORMAL:
$shEditor .= "<input type='text' value=\"{$oFilter->getData()}\" name='s{$sColumn}Data$sId' size='30' />";
break;
case FILTER_VALUES_ENUM:
case FILTER_VALUES_OPTION_ENUM:
$shEditor .= $this->getEnumEditor($oColumn, $oFilter, $sId);
break;
}
return $shEditor;
}
public function getEnumEditor($oColumn, $oFilter, $sId)
{
$sColumn = $this->escapeChars($oFilter->getColumn());
$aOptions = $oColumn->getValueTypeData();
$aOptionNames = $oColumn->getValueTypeDataDisplay();
$sData = $oFilter->getData();
$shEditor = "<select name=\"s{$sColumn}Data$sId\">";
if($sData)
$shEditor .= "<option value=\"\">-- remove --</option>";
else
$shEditor .= "<option value=\"\">-- select --</option>";
for($i = 0; $i < sizeof($aOptions); $i++)
{
$sOption = $aOptions[$i];
$sSelected = '';
if($sData == $sOption)
$sSelected = ' selected="selected"';
$shEditor .= "<option value=\"$sOption\"$sSelected>{$aOptionNames[$i]}</option>";
}
$shEditor .= "</select>";
return $shEditor;
}
/* Get filter data formatted to fit in a URL */
public function getUrlData()
{
$shEditor = '';
$aCounts = array();
foreach($this->oFilterSet->getFilters() as $oFilter)
{
$sColumn = $oFilter->getColumn();
if(!array_key_exists($sColumn, $aCounts))
$aCounts[$sColumn] = 0;
$shEditor .= $this->getUrlElement($aCounts[$sColumn], $oFilter);
$shEditor .= '<br />';
$aCounts[$sColumn]++;
}
return $shEditor;
}
/* Get a list of hidden input tags to preserve form data */
public function getHiddenFormData()
{
$shEditor = '';
$aCounts = array();
foreach($this->oFilterSet->getFilters() as $oFilter)
{
$sColumn = $oFilter->getColumn();
if(!array_key_exists($sColumn, $aCounts))
$aCounts[$sColumn] = 0;
$shEditor .= $this->getHiddenInputTag($aCounts[$sColumn], $oFilter);
$shEditor .= '<br />';
$aCounts[$sColumn]++;
}
return $shEditor;
}
public function getEditor()
{
$shNewItemsEditor = '';
$shCurrentItemsEditor = '';
$aCounts = array();
if(sizeof($this->oFilterSet->getFilters()))
$shCurrentItemsEditor .= '<br /><b>Active filters</b><br />';
foreach($this->oFilterSet->getFilters() as $oFilter)
{
$sColumn = $oFilter->getColumn();
if(!array_key_exists($sColumn, $aCounts))
$aCounts[$sColumn] = 0;
if($oFilter->getOperatorId() == FILTER_OPTION_BOOL)
$shCurrentItemsEditor .= $this->getOptionBoolEditor($aCounts[$sColumn], $oFilter);
else
$shCurrentItemsEditor .= $this->getItemEditor($aCounts[$sColumn], $oFilter);
$shCurrentItemsEditor .= '<br />';
$aCounts[$sColumn]++;
}
$shNewItemsEditor .= '<b>Add new filter</b> <i>(You don&#8217;t have to fill out all rows.)</i><br />';
/* Show errors, if any */
if($this->sErrors)
$shNewItemsEditor .= "<font color=\"red\">{$this->sErrors}</font>";
foreach($this->aFilterInfo as $oOption)
{
$oDummyFilter = new Filter($oOption->getColumn(), 0, '');
$aTypes = $oOption->getTypes();
if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL)
{
if(!array_key_exists($oOption->getColumn(), $aCounts))
$shNewItemsEditor .= $this->getOptionBoolEditor(-1, $oDummyFilter);
$shNewItemsEditor .= '<br />';
} else
{
/* Make necessary checks for filters that are only supposed to be shown once */
if($oOption->getValueType() != FILTER_VALUES_OPTION_ENUM || !array_key_exists($oOption->getColumn(), $aCounts))
{
$shNewItemsEditor .= $this->getItemEditor(-1, $oDummyFilter);
$shNewItemsEditor .= '<br />';
}
}
}
return $shNewItemsEditor.$shCurrentItemsEditor;
}
public function getFilterInfo()
{
return $this->aFilterInfo;
}
/* Reads all input related to filters for the given table column */
public function readInputForColumn($aClean, FilterInfo $oOption)
{
$aReturn = array();
$bChangedOption = false;
for($i = 0; array_key_exists('i'.$this->escapeChars($oOption->getColumn())."Op$i", $aClean); $i++)
{
$sColumn = $this->escapeChars($oOption->getColumn());
$sData = query_escape_string(getInput("s{$sColumn}Data$i", $aClean));
$iOp = $aClean["i{$sColumn}Op$i"];
if(!$iOp)
continue;
$oFilter = new Filter($oOption->getColumn(), $iOp, $sData);
/* Only show an option as an active filter if it has been changed
from the default */
if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL || $oOption->getValueType() == FILTER_VALUES_OPTION_ENUM)
{
if($oOption->getValueType() == FILTER_VALUES_OPTION_BOOL)
{
/* The default option is the first entry in the list of choices */
$aChoices = $oOption->getValueTypeData();
$sDefault = $aChoices[0];
if(!$sData)
$sData = 'false';
if($sData == $sDefault)
continue;
}
if($i > 0)
continue;
$bChangedOption = true;
}
if(!$sData)
continue;
$aReturn[] = $oFilter;
}
if(array_key_exists('i'.$this->escapeChars($oOption->getColumn())."Op", $aClean))
{
$sColumn = $this->escapeChars($oOption->getColumn());
$i = sizeof($aReturn);
$sData = query_escape_string($aClean["s{$sColumn}Data"]);
$iOp = $aClean["i{$sColumn}Op"];
if($iOp && $sData && ($oOption->getValueType() != FILTER_VALUES_OPTION_BOOL || !$bChangedOoption))
{
$oFilter = new Filter($oOption->getColumn(), $iOp, $sData);
$aReturn[] = $oFilter;
} else if(!$iOp && $sData)
{
/* The user probably meant to add a filter, but forgot to seelect
a filter criterion */
$this->sErrors .= 'You need to select a filter criterion from the drop-down list<br />';
}
}
return $aReturn;
}
/* Reads an input array get enabled filters from form data.
The given TableFilterSet defines available options */
public function readInput($aClean)
{
$iCount = 0; // We set a maximum for how many filters a user can add,
// otherwise we may get a too long SQL query
foreach($this->getFilterInfo() as $oOption)
{
foreach($this->readInputForColumn($aClean, $oOption) as $oNewFilter)
{
$iCount ++;
$this->AddFilterObject($oNewFilter);
if($iCount > MAX_FILTERS)
break;
}
}
}
public function loadTable($sTableName)
{
$this->oFilterSet->loadTable($sTableName);
}
public function saveTable($sTableName)
{
$this->oFilterSet->saveTable($sTableName);
}
public function getFilterCount()
{
return $this->oFilterSet->getFilterCount();
}
/* Returns an array of options, where the keys are the columns and the members
are the settings themselves */
public function getOptions()
{
$aOptions = array();
foreach($this->oFilterSet->getFilters() as $oFilter)
{
if($oFilter->isOption())
$aOptions[$oFilter->getColumn()] = $oFilter->getData();
}
foreach($this->aFilterInfo as $oFilterInfo)
{
if($oFilterInfo->isOption() &&
!array_key_exists($oFilterInfo->getColumn(), $aOptions))
{
$aTypes = $oFilterInfo->getTypes();
if($oFilterInfo->getValueType() == FILTER_VALUES_OPTION_BOOL)
$sDefault = $aTypes[0];
else
$sDefault = '';
$aOptions[$oFilterInfo->getColumn()] = $sDefault;
}
}
return $aOptions;
}
public function getWhereClause()
{
return $this->oFilterSet->getWhereClause();
}
public function getTable($sTable, $iLimit = 0)
{
$hResult = $this->oFilterSet->getMatchedItems($sTable, $iLimit);
if(!$hResult)
return;
echo 'Selected '.$this->oFilterSet->getMatchedItemsCount($sTable).' rows<br><br>';
$oTable = new Table();
while($aRow = mysql_fetch_row($hResult))
{
$oRow = new TableRow();
foreach($aRow as $sCell)
{
$oRow->AddTextCell($sCell);
}
$oTable->AddRow($oRow);
}
return $oTable->getString();
}
}
?>

789
include/distribution.php Normal file
View File

@@ -0,0 +1,789 @@
<?php
/***************************************/
/* this class represents Distributions */
/***************************************/
require_once(BASE."include/mail.php");
require_once(BASE."include/util.php");
// Test class for handling Distributions.
class distribution {
var $iDistributionId;
var $sName;
var $sUrl;
var $sSubmitTime;
var $iSubmitterId;
private $sState;
var $aTestingIds;
// constructor, fetches the data.
function distribution($iDistributionId = null, $oRow = null)
{
$this->aTestingIds = array();
// we are working on an existing distribution.
if(!$iDistributionId && !$oRow)
return;
// We fetch the data related to this distribution.
if(!$oRow)
{
$sQuery = "SELECT *
FROM distributions
WHERE distributionId = '?'";
if($hResult = query_parameters($sQuery, $iDistributionId))
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iDistributionId = $oRow->distributionId;
$this->sName = $oRow->name;
$this->sUrl = $oRow->url;
$this->sSubmitTime = $oRow->submitTime;
$this->iSubmitterId = $oRow->submitterId;
$this->sState = $oRow->state;
}
/*
* We fetch Test Result Ids.
*/
if($_SESSION['current']->hasPriv("admin"))
{
$sQuery = "SELECT testingId
FROM testResults, ?.versions
WHERE
versions.value = testResults.testedRelease
AND
versions.product_id = '?'
AND
distributionId = '?'
ORDER BY testedRating,bugs.versions.id DESC";
} else /* only let users view test results that aren't queued and for apps that */
/* aren't queued or versions that aren't queued */
{
$sQuery = "SELECT testingId
FROM testResults, appFamily, appVersion, ?.versions
WHERE testResults.state = 'accepted' AND
versions.value = testResults.testedRelease
AND
versions.product_id = '?'
AND
testResults.versionId = appVersion.versionId AND
appFamily.appId = appVersion.appId AND
appFamily.state = 'accepted' AND
appVersion.state = 'accepted' AND
distributionId = '?'
ORDER BY testedRating,bugs.versions.id DESC";
}
if($hResult = query_parameters($sQuery, BUGZILLA_DB, BUGZILLA_PRODUCT_ID, $this->iDistributionId))
{
while($oRow = query_fetch_object($hResult))
{
$this->aTestingIds[] = $oRow->testingId;
}
}
}
// Creates a new distribution.
function create()
{
//Let's not create a duplicate
$sQuery = "SELECT *
FROM distributions
WHERE name = '?'";
$hResult = query_parameters($sQuery, $this->sName);
if($hResult && $oRow = query_fetch_object($hResult))
{
if(query_num_rows($hResult))
{
addmsg("There was an existing distribution called ".$this->sName.".", "red");
$this->distribution($oRow->distributionId);
/* Even though we did not create a new distribution, the caller is provided
with a valid distribution object. Thus no special handling is necessary,
so we return TRUE */
return TRUE;
}
}
$hResult = query_parameters("INSERT INTO distributions (name, url, submitTime, ".
"submitterId, state) ".
"VALUES ('?', '?', ?, '?', '?')",
$this->sName, $this->sUrl,
"NOW()",
$_SESSION['current']->iUserId,
$this->mustBeQueued() ? 'queued' : 'accepted');
if($hResult)
{
$this->iDistributionId = query_appdb_insert_id();
$this->distribution($this->iDistributionId);
$this->SendNotificationMail();
return true;
}
else
{
addmsg("Error while creating Distribution.", "red");
return false;
}
}
// Update Distribution.
function update()
{
// is the current user allowed to update this Distribution?
if(!$_SESSION['current']->hasPriv("admin") &&
!($_SESSION['current']->iUserId == $this->iSubmitterId))
{
return;
}
if(query_parameters("UPDATE distributions SET name = '?', url = '?' WHERE distributionId = '?'",
$this->sName, $this->sUrl, $this->iDistributionId))
{
$this->SendNotificationMail("edit");
return true;
} else
{
addmsg("Error while updating Distribution", "red");
return false;
}
}
function purge()
{
/* Is the current user allowed to delete this distribution? We allow
everyone to delete a queued, empty distribution, because it should be
deleted along with the last testData associated with it */
if(!($this->canEdit() || (!sizeof($this->aTestingIds) &&
$this->sState != 'accepted')))
return false;
// if the distribution has test results only enable an admin to delete
// the distribution
if(sizeof($this->aTestingIds) && !$_SESSION['current']->hasPriv("admin"))
return FALSE;
$bSuccess = TRUE;
foreach($this->objectGetChildren(true) as $oChild)
{
if(!$oChild->purge())
$bSuccess = FALSE;
}
// now delete the Distribution
$sQuery = "DELETE FROM distributions
WHERE distributionId = '?'
LIMIT 1";
if(!($hResult = query_parameters($sQuery, $this->iDistributionId)))
$bSuccess = FALSE;
return $bSuccess;
}
// Delete Distributution.
function delete()
{
/* Is the current user allowed to delete this distribution? We allow
everyone to delete a queued, empty distribution, because it should be
deleted along with the last testData associated with it */
if(!($this->canEdit() || (!sizeof($this->aTestingIds) &&
$this->sState != 'accepted')))
return false;
// if the distribution has test results only enable an admin to delete
// the distribution
if(sizeof($this->aTestingIds) && !$_SESSION['current']->hasPriv("admin"))
return FALSE;
$bSuccess = TRUE;
foreach($this->objectGetChildren() as $oChild)
{
if(!$oChild->delete())
$bSuccess = FALSE;
}
// now delete the Distribution
$sQuery = "UPDATE distributions SET state = 'deleted'
WHERE distributionId = '?'
LIMIT 1";
if(!($hResult = query_parameters($sQuery, $this->iDistributionId)))
$bSuccess = FALSE;
return $bSuccess;
}
// Move Distribution out of the queue.
function unQueue()
{
/* Check permissions */
if($this->mustBeQueued())
return FALSE;
// If we are not in the queue, we can't move the Distribution out of the queue.
if($this->sState != 'queued')
return false;
if(query_parameters("UPDATE distributions SET state = '?' WHERE distributionId = '?'",
'accepted', $this->iDistributionId))
{
$this->sState = 'accepted';
// we send an e-mail to interested people
$this->mailSubmitter("add");
$this->SendNotificationMail();
return true;
} else
{
addmsg("Error while unqueueing Distribution", "red");
return false;
}
}
function Reject($bSilent=false)
{
// is the current user allowed to reject this Distribution?
if(!$_SESSION['current']->hasPriv("admin"))
{
return false;
}
// If we are not in the queue, we can't move the Distribution out of the queue.
if($this->sState != 'queued')
return false;
return $this->delete();
}
function getTestResults($bIncludeDeleted = false)
{
if($bIncludeDeleted)
$sExcludeDeleted = "";
else
$sExcludeDeleted = " AND state != 'deleted'";
$aTests = array();
$sQuery = "SELECT * FROM testResults WHERE distributionId = '?'$sExcludeDeleted";
$hResult = query_parameters($sQuery, $this->iDistributionId);
while($oRow = mysql_fetch_object($hResult))
$aTests[] = new testData(null, $oRow);
return $aTests;
}
function objectGetChildren($bIncludeDeleted = false)
{
$aChildren = array();
foreach($this->getTestResults($bIncludeDeleted) as $oTest)
{
$aChildren += $oTest->objectGetChildren($bIncludeDeleted);
$aChildren[] = $oTest;
}
return $aChildren;
}
function ReQueue()
{
// is the current user allowed to requeue this data
if(!$_SESSION['current']->hasPriv("admin") &&
!($_SESSION['current']->iUserId == $this->iSubmitterId))
{
return false;
}
if(query_parameters("UPDATE testResults SET state = '?' WHERE testingId = '?'",
'queued', $this->iTestingId))
{
if(query_parameters("UPDATE distribution SET state = '?' WHERE distributionId = '?'",
'queued', $this->iDistributionId))
{
$this->sState = 'queued';
// we send an e-mail to interested people
$this->SendNotificationMail();
// the test data has been resubmitted
addmsg("The Distribution has been resubmitted", "green");
return true;
}
}
/* something has failed if we fell through to this point without */
/* returning */
addmsg("Error requeueing Distribution", "red");
return false;
}
function objectGetSubmitterId()
{
return $this->iSubmitterId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
$oSubmitter = new user($this->iSubmitterId);
if($bMailSubmitter)
{
switch($sAction)
{
case "delete":
$sSubject = "Submitted distribution deleted";
$sMsg = "The distribution you submitted (".$this->sName.") has been ".
"deleted.\n";
break;
}
$aMailTo = null;
} else
{
switch($sAction)
{
case "delete":
$sSubject = "Distribution ".$this->sName." deleted";
$sMsg = "";
break;
}
$aMailTo = User::get_notify_email_address_list(null, null);
}
return array($sSubject, $sMsg, $aMailTo);
}
function mailSubmitter($sAction="add")
{
global $aClean;
if($this->iSubmitterId)
{
$oSubmitter = new User($this->iSubmitterId);
switch($sAction)
{
case "add":
{
$sSubject = "Submitted Distribution accepted";
$sMsg = "The Distribution you submitted (".$this->sName.") has been accepted.\n";
}
break;
case "delete":
{
$sSubject = "Submitted Distribution deleted";
$sMsg = "The Distribution you submitted (".$this->sName.") has been deleted.";
$sMsg .= "Reason given:\n";
$sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any
}
break;
}
$sMsg .= "We appreciate your help in making the Application Database better for all users.";
mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg);
}
}
function SendNotificationMail($sAction="add",$sMsg=null)
{
global $aClean;
switch($sAction)
{
case "add":
if($this->sState == 'accepted')
{
$sSubject = "Distribution ".$this->sName." added by ".
$_SESSION['current']->sRealname;
$sMsg = $this->objectMakeUrl()."\n";
if($this->iSubmitterId)
{
$oSubmitter = new User($this->iSubmitterId);
$sMsg .= "This Distribution has been submitted by ".$oSubmitter->sRealname.".";
$sMsg .= "\n";
$sMsg .= "Appdb admin reply text:\n";
$sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any
}
addmsg("The Distribution was successfully added into the database.", "green");
} else // test data queued.
{
$sSubject = "Distribution ".$this->sName." submitted by ".$_SESSION['current']->sRealname;
$sMsg .= "This test data has been queued.";
$sMsg .= "\n";
addmsg("The Distribution you submitted will be added to the database after being reviewed.", "green");
}
break;
case "edit":
$sSubject = "Distribution ".$this->sName." has been modified by ".$_SESSION['current']->sRealname;
$sMsg = $this->objectMakeUrl()."\n";
addmsg("Distribution modified.", "green");
break;
case "delete":
$sSubject = "Distribution ".$this->sName." has been deleted by ".$_SESSION['current']->sRealname;
// if sReplyText is set we should report the reason the data was deleted
if($aClean['sReplyText'])
{
$sMsg .= "Reason given:\n";
$sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any
}
addmsg("Distribution deleted.", "green");
break;
case "reject":
$sSubject = "Distribution '".$this->sName." has been rejected by ".
$_SESSION['current']->sRealname;
$sMsg = $this->objectMakeUrl()."\n";
// if sReplyText is set we should report the reason the data was rejected
if($aClean['sReplyText'])
{
$sMsg .= "Reason given:\n";
$sMsg .= $aClean['sReplyText']."\n"; // append the reply text, if there is any
}
addmsg("Distribution rejected.", "green");
break;
}
$sEmail = User::get_notify_email_address_list(null, null);
if($sEmail)
mail_appdb($sEmail, $sSubject ,$sMsg);
}
function outputEditor()
{
echo "<table width='100%' border=0 cellpadding=2 cellspacing=0>\n";
$this->sName = str_replace('"', '&quot;', $this->sName);
// Name
echo html_tr(array(
array("<b>Distribution Name:</b>", 'align=right class="color0"'),
array('<input type=text name="sDistribution" value="'.$this->sName.
'" size="60" />', 'class="color0"')
));
// URL
echo html_tr(array(
array("<b>Distribution URL:</b>", 'align=right class="color0"'),
array('<input type=text name="sUrl" value="'.$this->sUrl.
'" size="60" />', 'class="color0"')
));
echo "</table>\n";
if($this->iDistributionId)
{
echo '<input type="hidden" name="iDistributionId" '.
'value="'.$this->iDistributionId.'">',"\n";
}
}
/* retrieves values from $_REQUEST that were output by outputEditor() */
/* $aValues can be $_REQUEST or any array with the values from outputEditor() */
function GetOutputEditorValues($aValues)
{
if($aClean['iDistributionId'])
$this->iDistributionId = $aValues['iDistributionId'];
$this->sName = $aValues['sDistribution'];
$this->sUrl = $aValues['sUrl'];
}
function objectGetFilterInfo()
{
$oFilter = new FilterInterface();
$oFilter->AddFilterInfo('name', 'Name', array(FILTER_CONTAINS, FILTER_STARTS_WITH, FILTER_ENDS_WITH), FILTER_VALUES_NORMAL);
return $oFilter;
}
/* Get the total number of Distributions in the database */
function objectGetEntriesCount($sState, $oFilter = null)
{
/* Not implemented */
if($sState == 'rejected')
return FALSE;
$sWhereFilter = $oFilter ? $oFilter->getWhereClause() : '';
if($sWhereFilter)
$sWhereFilter = " AND $sWhereFilter";
$hResult = query_parameters("SELECT count(distributionId) as num_dists FROM
distributions WHERE state='?' $sWhereFilter",
$sState);
if($hResult)
{
$oRow = query_fetch_object($hResult);
return $oRow->num_dists;
}
return 0;
}
/* Make a dropdown list of distributions */
function make_distribution_list($varname, $cvalue)
{
$sQuery = "SELECT name, distributionId FROM distributions
WHERE state = 'accepted'
ORDER BY name";
$hResult = query_parameters($sQuery);
if(!$hResult) return;
echo "<select name='$varname'>\n";
echo "<option value=\"\">Choose ...</option>\n";
while(list($name, $value) = query_fetch_row($hResult))
{
if($value == $cvalue)
echo "<option value=$value selected>$name\n";
else
echo "<option value=$value>$name\n";
}
echo "</select>\n";
}
function objectGetHeader()
{
$oTableRow = new TableRowSortable();
$oTableRow->AddSortableTextCell("Distribution name", "name");
$oTableCell = new TableCell("Test reports");
$oTableRow->AddCell($oTableCell);
$oTableRow->AddTextCell("Distribution url");
return $oTableRow;
}
public static function objectGetSortableFields()
{
return array('name');
}
public static function objectGetDefaultSort()
{
return 'name';
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "name", $bAscending = TRUE, $oFilter = null)
{
/* Not implemented */
if($sState == 'rejected')
return FALSE;
/* Only users with edit privileges are allowed to view queued
items, so return NULL in that case */
if($sState != 'accepted' && !distribution::canEdit())
return NULL;
$sOrder = $bAscending ? "ASC" : "DESC";
/* If row limit is 0 we want to fetch all rows */
if(!$iRows)
$iRows = distribution::objectGetEntriesCount($sState, $oFilter);
$sWhereFilter = $oFilter ? $oFilter->getWhereClause() : '';
if($sWhereFilter)
$sWhereFilter = " AND $sWhereFilter";
$sQuery = "SELECT * FROM distributions
WHERE state = '?' $sWhereFilter ORDER BY $sOrderBy $sOrder LIMIT ?,?";
return query_parameters($sQuery, $sState,
$iStart, $iRows);
}
function objectGetTableRow()
{
$oTableRow = new TableRow();
$oTableRow->AddTextCell($this->objectMakeLink());
$oTableCell = new TableCell(sizeof($this->aTestingIds));
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell("$this->sUrl");
$oTableCell->SetCellLink($this->sUrl);
$oTableRow->AddCell($oTableCell);
// enable the 'delete' action if this distribution has no test results
$bDeleteLink = sizeof($this->aTestingIds) ? FALSE : TRUE;
$oOMTableRow = new OMTableRow($oTableRow);
$oOMTableRow->SetHasDeleteLink($bDeleteLink);
return $oOMTableRow;
}
public function objectGetState()
{
return $this->sState;
}
// Whether the user has permission to edit distributions
function canEdit()
{
if($_SESSION['current']->hasPriv("admin"))
return TRUE;
/* Maintainers are allowed to process queued test results and therefore also
queued distributions */
if(is_object($this) && $this->sState != 'accepted' &&
maintainer::isUserMaintainer($_SESSION['current']))
return TRUE;
return FALSE;
}
function mustBeQueued()
{
if($_SESSION['current']->hasPriv("admin") ||
maintainer::isUserMaintainer($_SESSION['current']))
return FALSE;
else
return TRUE;
}
function objectHideDelete()
{
return TRUE;
}
function display()
{
echo "Distribution Name:";
if($this->sUrl)
echo "<a href='".$this->sUrl."'>";
echo $this->sName;
if ($this->sUrl)
{
echo " (".$this->sUrl.")";
echo "</a> <br>\n";
} else
{
echo "<br>\n";
}
if($this->aTestingIds)
{
echo '<p><span class="title">Test Results for '.$this->sName.'</span><br>',"\n";
echo '<table width="100%" border="1">',"\n";
echo '<thead class="historyHeader">',"\n";
echo '<tr>',"\n";
echo '<td>Application Version</td>',"\n";
echo '<td>Submitter</td>',"\n";
echo '<td>Date Submitted</td>',"\n";
echo '<td>Wine version</td>',"\n";
echo '<td>Installs?</td>',"\n";
echo '<td>Runs?</td>',"\n";
echo '<td>Rating</td>',"\n";
echo '</tr></thead>',"\n";
foreach($this->aTestingIds as $iTestingId)
{
$oTest = new testData($iTestingId);
if($oTest->objectGetState() != $this->objectGetState())
continue;
$oVersion = new Version($oTest->iVersionId);
$oApp = new Application($oVersion->iAppId);
$oSubmitter = new User($oTest->iSubmitterId);
$bgcolor = $oTest->sTestedRating;
/* make sure the user can view the versions we list in the table */
/* otherwise skip over displaying the entries in this table */
if(!$_SESSION['current']->canViewApplication($oApp))
continue;
if(!$_SESSION['current']->canViewVersion($oVersion))
continue;
echo '<tr class='.$bgcolor.'>',"\n";
echo '<td><a href="'.$oVersion->objectMakeUrl().'&amp;iTestingId='.$oTest->iTestingId.'">',"\n";
echo version::fullName($oVersion->iVersionId).'</a></td>',"\n";
echo '<td>',"\n";
echo $oSubmitter->objectMakeLink();
echo '</td>',"\n";
echo '<td>'.date("M d Y", mysqldatetime_to_unixtimestamp($oTest->sSubmitTime)).'</td>',"\n";
echo '<td>'.$oTest->sTestedRelease.'&nbsp;</td>',"\n";
echo '<td>'.$oTest->sInstalls.'&nbsp;</td>',"\n";
echo '<td>'.$oTest->sRuns.'&nbsp;</td>',"\n";
echo '<td>'.$oTest->sTestedRating.'&nbsp;</td>',"\n";
if ($_SESSION['current']->hasAppVersionModifyPermission($oVersion))
{
echo '<td><a href="'.$oTest->objectMakeUrl().'">',"\n";
echo 'Edit</a></td>',"\n";
}
echo '</tr>',"\n";
}
echo '</table>',"\n";
}
}
/* Make a URL for viewing the specified distribution */
function objectMakeUrl()
{
$oObject = new objectManager("distribution", "View Distribution");
return $oObject->makeUrl("view", $this->iDistributionId);
}
/* Make an HTML link for viewing the specified distirbution */
function objectMakeLink()
{
return "<a href=\"".$this->objectMakeUrl()."\">$this->sName</a>";
}
function objectMoveChildren($iNewId)
{
/* Keep track of how many children we modified */
$iCount = 0;
foreach($this->aTestingIds as $iTestId)
{
$oTest = new testData($iTestId);
$oTest->iDistributionId = $iNewId;
if($oTest->update(TRUE))
$iCount++;
else
return FALSE;
}
return $iCount;
}
function objectGetItemsPerPage($sState = 'accepted')
{
$aItemsPerPage = array(25, 50, 100, 200);
$iDefaultPerPage = 25;
return array($aItemsPerPage, $iDefaultPerPage);
}
function objectGetid()
{
return $this->iDistributionId;
}
function allowAnonymousSubmissions()
{
return FALSE;
}
function objectShowAddEntry()
{
return TRUE;
}
}
?>

486
include/downloadurl.php Normal file
View File

@@ -0,0 +1,486 @@
<?php
/**
* Functions related to download links
*/
require_once(BASE."include/appData.php");
class downloadurl
{
var $iId;
var $iVersionId;
var $sDescription;
var $sUrl;
var $sSubmitTime;
var $iSubmitterId;
var $bQueued;
/* Fetch the data if id is given */
function downloadurl($iId = NULL, $oRow = NULL)
{
if(!$iId && !$oRow)
return;
if(!$oRow)
{
$hResult = query_parameters("SELECT id, versionId, description, url,
submitTime, submitterId, state FROM appData WHERE id = '?'",
$iId);
if($hResult && query_num_rows($hResult))
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iId = $oRow->id;
$this->iVersionId = $oRow->versionId;
$this->sDescription = $oRow->description;
$this->sUrl = $oRow->url;
$this->sSubmitTime = $oRow->submitTime;
$this->iSubmitterId = $oRow->submitterId;
$this->bQueued = ($oRow->state == 'queued') ? TRUE : FALSE;
}
}
/* Display download links for a given version */
function display($iVersionId)
{
if(!($hResult = appData::getData($iVersionId, "downloadurl")))
return FALSE;
// we're appending, so initialize it
$sReturn = '';
for($i = 0; $oRow = query_fetch_object($hResult); $i++)
{
$sReturn .= html_tr(array(
"<b>Free Download</b>",
"<a href=\"$oRow->url\">$oRow->description</a>"),
"color1");
}
return $sReturn;
}
public function objectGetParent($sClass = '')
{
$oAppData = new appData($this->iId, null, $this);
return $oAppData->objectGetParent();
}
public function objectSetParent($iNewId, $sClass = '')
{
if($this->iVersionId || !$this->iAppId)
$this->iVersionId = $iNewId;
else
$this->iAppId = $iNewId;
}
function objectGetChildren($bIncludeDeleted = false)
{
/* We have none */
return array();
}
/* Output an editor for Download URL fields */
function outputEditor($oVersion = null, $sFormAction = null)
{
/* If we do not get any parameters we try to behave like a proper objectManager
object, by only showing an editor for one entry instead of several. This
code is sort of hacky, and should be fixed once the rest of the downloadurl
code is fully adapted to the objectManager */
if(!$oVersion && !$sFormAction)
{
global $aClean;
echo downloadurl::outputEditorSingle($this->iVersionId);
}
if(!$oVersion || !$sFormAction)
return FALSE;
/* Check for correct permissions */
if(!downloadurl::canEdit($oVersion->iVersionId))
return FALSE;
$hResult = appData::getData($oVersion->iVersionId, "downloadurl");
$sReturn .= html_frame_start("Download URL", "90%", "", 0);
$sReturn .= "<form method=\"post\" action=\"$sFormAction\">\n";
$sReturn .= html_table_begin("border=0 cellpadding=5 cellspacing=0 width=100%");
$sReturn .= html_tr(array(
array("<b>Remove</b>", "width=\"90\""),
"<b>Description</b>",
"<b>URL</b>"
),
"color0");
$sReturn .= html_tr(array(
"&nbsp;",
"<input type=\"text\" size=\"45\" name=\"".
"sDescriptionNew\">",
"<input type=\"text\" size=\"45\" name=\"sUrlNew\">"),
"color4");
if($hResult)
{
for($i = 1; $oRow = query_fetch_object($hResult); $i++)
{
$sReturn .= html_tr(array(
"<input type=\"checkbox\" name=\"bRemove$oRow->id\" ".
"value=\"true\">",
"<input type=\"text\" size=\"45\" name=\"".
"sDescription$oRow->id\" value=\"$oRow->description\">",
"<input type=\"text\" size=\"45\" name=\"sUrl$oRow->id\" ".
"value=\"$oRow->url\">"),
($i % 2) ? "color0" : "color4");
}
}
$sReturn .= html_table_end();
$sReturn .= "<div align=\"center\"><input type=\"submit\" value=\"".
"Update Download URLs\" name=\"sSubmit\"></div>\n";
$sReturn .= "<input type=\"hidden\" name=\"iVersionId\" ".
"value=\"$oVersion->iVersionId\">\n";
$sReturn .= "<input type=\"hidden\" name=\"iAppId\" ".
"value=\"$oVersion->iAppId\">\n";
$sReturn .= "</form>\n";
$sReturn .= html_frame_end("&nbsp;");
return $sReturn;
}
function objectGetSubmitterId()
{
return $this->iSubmitterId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
/* We don't do this at the moment */
return array(null, null, null);
}
/* Process data from a Download URL form */
function ProcessForm($aValues)
{
/* Check that we are processing a Download URL form */
if($aValues["sSubmit"] != "Update Download URLs")
return FALSE;
/* Check permissions */
if(!downloadurl::canEdit($aValues["iVersionId"]))
return FALSE;
if(!($hResult = query_parameters("SELECT COUNT(*) as num FROM appData
WHERE TYPE = '?' AND versionId = '?' AND state = 'accepted'",
"downloadurl", $aValues["iVersionId"])))
return FALSE;
if(!($oRow = query_fetch_object($hResult)))
return FALSE;
$num = $oRow->num;
/* Update URLs. Nothing to do if none are present in the database */
if($num)
{
if(!$hResult = appData::getData($aValues["iVersionId"], "downloadurl"))
return FALSE;
while($oRow = query_fetch_object($hResult))
{
$oDownloadurl = new downloadurl($oRow->id);
/* Remove URL */
if($aValues["bRemove$oRow->id"])
{
if(!$oDownloadurl->delete())
return FALSE;
$sWhatChangedRemove .= "Removed\nURL: $oRow->url\n".
"Description: $oRow->description\n\n";
}
/* Change description/URL */
if(($aValues["sDescription$oRow->id"] != $oRow->description or
$aValues["sUrl$oRow->id"] != $oRow->url) &&
$aValues["sDescription$oRow->id"] && $aValues["sUrl$oRow->id"])
{
$oDownloadurl->sDescription =
$aValues["sDescription$oRow->id"];
$oDownloadurl->sUrl = $aValues["sUrl$oRow->id"];
if(!$oDownloadurl->update())
return FALSE;
$sWhatChangedModify .= "Modified\nOld URL: $oRow->url\nOld ".
"Description: $oRow->description\nNew URL: ".
$aValues["sUrl$oRow->id"]."\nNew Description: ".
$aValues["sDescription$oRow->id"]."\n\n";
}
}
}
/* Insert new URL */
if($aValues["sDescriptionNew"] && $aValues["sUrlNew"])
{
$oDownloadurl = new downloadurl();
$oDownloadurl->iVersionId = $aValues["iVersionId"];
$oDownloadurl->sUrl = $aValues["sUrlNew"];
$oDownloadurl->sDescription = $aValues["sDescriptionNew"];
if(!$oDownloadurl->create())
return FALSE;
$sWhatChanged = "Added\nURL: ".$aValues["sUrlNew"]."\nDescription: ".
$aValues["sDescriptionNew"]."\n\n";
}
$sWhatChanged .= "$sWhatChangedRemove$sWhatChangedModify";
if($sWhatChanged && $sEmail =
User::get_notify_email_address_list($aValues['iVersionId']))
{
$oVersion = new Version($aValues["iVersionId"]);
$sSubject = "Download URLs for ".version::fullName($oVersion->iVersionId).
" updated by ".$_SESSION['current']->sRealname;
$sMsg = $oVersion->objectMakeUrl();
$sMsg .= "\n\n";
$sMsg .= "The following changed were made\n\n";
$sMsg .= "$sWhatChanged\n\n";
mail_appdb($sEmail, $sSubject, $sMsg);
}
return TRUE;
}
function objectGetState()
{
return ($this->bQueued) ? 'queued' : 'accepted';
}
function canEdit($iVersionId = NULL)
{
if($_SESSION['current']->hasPriv("admin") ||
($iVersionId &&
maintainer::isUserMaintainer($_SESSION['current'], $iVersionId)))
{
return TRUE;
} else
{
$oVersion = new version($this->iVersionId);
return $oVersion->canEdit();
}
}
/* Output an editor for a single new URL */
function outputEditorSingle($iVersionId = NULL, $aValues = NULL)
{
if($aValues["sDownloadUrlUrl"] &&
$aValues["sDownloadUrlDescription"])
{
$sDownloadUrlUrl = $aValues["sDownloadUrlUrl"];
$sDownloadUrlDescription = $aValues["sDownloadUrlDescription"];
} else if($iVersionId)
{
/* This illustrates the importance of converting downloadurl completely
to the objectManager model. If we don't get a match searching for
a queued entry, try finding a rejected one. */
if(($hResult = appData::getData($iVersionId, "downloadurl",
TRUE, TRUE, FALSE)) ||
$hResult = appData::getData($iVersionId, "downloadurl",
TRUE, TRUE, TRUE))
{
$oRow = query_fetch_object($hResult);
$sDownloadUrlUrl = $oRow->url;
$sDownloadUrlDescription = $oRow->description;
}
}
$sReturn .= html_frame_start("Download URL","90%");
$sReturn .= html_table_begin("width='100%' border=0 cellpadding=2 cellspacing=0");
$sReturn .= "A place where this version can be downloaded for free".
" (if applicable). You can add more links later.<br>";
$sReturn .= html_tr(array(
array("<b>Download URL:</b>", "align=right"),
array("<input type=\"text\" name=\"sDownloadUrlUrl\" ".
"value=\"$sDownloadUrlUrl\" size=\"60\">",
"class=\"color4\"")),
"color0");
$sReturn .= html_tr(array(
array("<b>Download URL Description:</b>", "align=right"),
array("<input type=\"text\" name=\"sDownloadUrlDescription\" ".
"value=\"$sDownloadUrlDescription\" size=\"60\">",
"class=\"color4\"")),
"color0");
$sReturn .= html_table_end();
$sReturn .= html_frame_end("nbsp;");
return $sReturn;
}
function create()
{
if(!$this->sUrl or !$this->sDescription or !$this->iVersionId)
return FALSE;
$hResult = query_parameters("INSERT INTO appData (versionId, type,
description, url, state, submitTime, submitterId)
VALUES('?', '?', '?', '?', '?', ?, '?')",
$this->iVersionId, "downloadurl", $this->sDescription,
$this->sUrl,
$this->mustBeQueued() ? 'queued' : 'accepted',
"NOW()",
$_SESSION['current']->iUserId);
$this->iId = query_appdb_insert_id();
if(!$hResult)
return FALSE;
return TRUE;
}
function update()
{
if(!$this->bQueued && !$this->canEdit($this->iVersionId))
return FALSE;
if(!$this->sDescription && !$this->sUrl)
{
$this->delete();
return true;
}
$hResult = query_parameters("UPDATE appData SET
description = '?', url = '?', versionId = '?' WHERE id = '?'",
$this->sDescription, $this->sUrl, $this->iVersionId, $this->iId);
if(!$hResult)
return FALSE;
return TRUE;
}
function unQueue()
{
if($this->mustBeQueued())
return FALSE;
$hResult = query_parameters("UPDATE appData SET state = '?'
WHERE id = '?'",
'accepted', $this->iId);
if(!$hResult)
return FALSE;
return TRUE;
}
function purge()
{
return $this->delete();
}
function delete()
{
if(!downloadurl::canEdit($this->iVersionId))
return FALSE;
if(!query_parameters("DELETE FROM appData WHERE id = '?'", $this->iId))
return FALSE;
return TRUE;
}
function reQueue()
{
$oAppData = new AppData($this->iId);
return $oAppData->reQueue();
}
function reject()
{
$oAppData = new AppData($this->iId);
return $oAppData->reject();
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true)
{
return appData::objectGetEntries($sState, $iRows, $iStart, $sOrderBy, $bAscending, 'downloadurl');
}
function objectGetEntriesCount($sState)
{
return appData::objectGetEntriesCount($sState, 'downloadurl');
}
function objectGetHeader()
{
return appData::objectGetHeader("downloadurl");
}
function objectGetTableRow()
{
$oAppData = new AppData();
return $oAppData->objectGetTableRow();
}
function getOutputEditorValues($aClean)
{
$this->sUrl = $aClean['sDownloadUrlUrl'];
$this->sDescription = $aClean['sDownloadUrlDescription'];
}
function mustBeQueued()
{
if($this)
{
$oAppData = new appData();
$oAppData->iVersionId = $this->iVersionId;
$oAppData->iAppId = NULL;
return $oAppData->mustBeQueued();
} else
return appData::mustBeQueued();
}
function allowAnonymousSubmissions()
{
return FALSE;
}
function objectMakeLink()
{
/* FIXME: not implemented */
return TRUE;
}
function objectMakeUrl()
{
/* FIXME: not implemented */
return TRUE;
}
function objectGetId()
{
return $this->iId;
}
}
?>

104
include/error_log.php Normal file
View File

@@ -0,0 +1,104 @@
<?php
define("ERROR_SQL", "sql_error");
define("ERROR_GENERAL", "general_error");
class error_log
{
function log_error($sErrorType, $sLogText)
{
global $aClean;
/* dump the contents of $_REQUEST and $aClean to a variable */
/* so we can output that to the log entry. it should make it much easier */
/* to determine when and where the error took place */
ob_start();
echo "REQUEST:\n";
var_dump($_REQUEST);
echo "aClean:\n";
var_dump($aClean);
$sRequestText = ob_get_contents();
ob_end_clean();
$sQuery = 'INSERT INTO error_log (submitTime, userid, type, log_text, request_text, deleted) '.
"VALUES(?, '?', '?', '?', '?', '?')";
$iUser = (isset($_SESSION['current']) ? $_SESSION['current']->iUserId : 0);
$hResult = query_parameters($sQuery,
"NOW()",
$iUser,
$sErrorType,
$sLogText,
$sRequestText,
'0');
}
/* get a backtrace and log it to the database */
function logBackTrace($sDescription)
{
ob_start();
print_r(debug_backtrace());
$sDebugOutput = ob_get_contents();
ob_end_clean();
error_log::log_error("general_error", $sDescription.' '.$sDebugOutput);
}
function getEntryCount()
{
$sQuery = "SELECT count(*) as cnt FROM error_log WHERE deleted = '0'";
$hResult = query_parameters($sQuery);
$oRow = query_fetch_object($hResult);
return $oRow->cnt;
}
/* purge all of the current entries from the error log */
function flush()
{
$sQuery = "UPDATE error_log SET deleted='1'";
$hResult = query_parameters($sQuery);
if($hResult) return true;
else return false;
}
function mail_admins_error_log($sSubject = "")
{
$sSubject .= "Database Error log\r\n";
$sEmail = User::get_notify_email_address_list(null, null); /* get list admins */
$sQuery = "SELECT * from error_log WHERE deleted='0' ORDER BY submitTime";
$hResult = query_parameters($sQuery);
$bEmpty = false;
if(query_num_rows($hResult) == 0)
$bEmpty = true;
$sMsg = "Log entries:\r\n";
$sMsg.= "\r\n";
$sMsg.= "Submit time userid type\r\n";
$sMsg.= "log_text\r\n";
$sMsg.= "request_text\r\n";
$sMsg.="----------------------------------\r\n\r\n";
/* append each log entry to $sMsg */
while($oRow = query_fetch_object($hResult))
{
$sMsg.=$oRow->submitTime." ".$oRow->userid." ".$oRow->type."\r\n";
$sMsg.= "---------------------\r\n";
$sMsg.=$oRow->log_text."\r\n";
$sMsg.= "---------------------\r\n";
$sMsg.=$oRow->request_text."\r\n\r\n";
}
/* if we had no entries we should indicate */
/* that the error log is empty */
if($bEmpty)
$sMsg = "The error log is empty.\r\n";
if($sEmail)
mail_appdb($sEmail, $sSubject, $sMsg);
}
}
?>

117
include/filter.php Normal file
View File

@@ -0,0 +1,117 @@
<?php
$aClean = array();
filter_perform_filtering();
/* perform input variable filtering */
function filter_perform_filtering()
{
// if filtering failed post the error
$sResult = filter_gpc();
if($sResult)
{
util_show_error_page_and_exit($sResult);
}
}
/*
* Make all get/post/cookies variable clean based on their names.
* Returns an error string if failure occurs, null if successful
*/
function filter_gpc()
{
global $aClean;
$sErrorSuggestion = " Please try clearing out your cookies. If the problem continues ".
" please email ".APPDB_OWNER_EMAIL." with the error text.";
$aKeys = array_keys($_REQUEST);
for($i=0; $i < sizeof($aKeys); $i++)
{
// NOTE: useful for debugging
//echo "'".$aKeys[$i]."' = '".$_REQUEST[$aKeys[$i]]."'\n";
// Special cases for variables that don't fit our filtering scheme
// don't filter the AppDB session cookie and MAX_FILE_SIZE
// and the DialogX values that xinha uses
// NOTE: we must use === when comparing the return value of strpos
// against a value, otherwise if strpos() returns false indicating that
// the value wasn't found strpos(something) == 0 will still be true
if((strpos($aKeys[$i], "Dialog") === 0) ||
(strpos($aKeys[$i], "XinhaColorPicker") === 0) || // Xinha variables
($aKeys[$i] == "cx") || // google custom search variable
($aKeys[$i] == "cof") || // google custom search variable
($aKeys[$i] == "q")) // google custom search variable
{
// copy the key over to the clean array
// NOTE: we do not strip html tags or trim any Xinha variables
// because Xinha is a html editor and removing html tags
// would break the ability to use Xinha to create or edit html
$aClean[$aKeys[$i]] = $_REQUEST[$aKeys[$i]];
continue; // go to the next entry
} else if($aKeys[$i] == "whq_appdb" || ($aKeys[$i] == "MAX_FILE_SIZE")
|| ($aKeys[$i] == "PHPSESSID")
|| (strpos($aKeys[$i], "pref_") === 0)) // other variables
{
// copy the key over to the clean array after stripping tags and trimming
$aClean[$aKeys[$i]] = trim(strip_tags($_REQUEST[$aKeys[$i]]));
continue; // go to the next entry
}
switch($aKeys[$i][0])
{
case "i": // integer
case "f": // float
if(is_numeric($_REQUEST[$aKeys[$i]]))
$aClean[$aKeys[$i]] = $_REQUEST[$aKeys[$i]];
else if(empty($_REQUEST[$aKeys[$i]]))
$aClean[$aKeys[$i]] = 0;
else if(is_numeric(trim($_REQUEST[$aKeys[$i]]))) // try clearing whitespace
$aClean[$aKeys[$i]] = trim($_REQUEST[$aKeys[$i]]);
else
return "Fatal error: ".$aKeys[$i]." should be a numeric value. ".
$sErrorSuggestion;
break;
case "b": // boolean
if($_REQUEST[$aKeys[$i]]=="true" || $_REQUEST[$aKeys[$i]]=="false")
$aClean[$aKeys[$i]] = $_REQUEST[$aKeys[$i]];
else
return "Fatal error: ".$aKeys[$i]." should be a boolean value. ".
$sErrorSuggestion;
break;
case "s": // string
switch($aKeys[$i][1])
{
case "h": // HTML string
$aClean[$aKeys[$i]] = trim($_REQUEST[$aKeys[$i]]);
// if there is no content and no image, make the variable empty
if(strip_tags($aClean[$aKeys[$i]],'<img>')=="")
$aClean[$aKeys[$i]] = "";
break;
default: // normal string (no HTML)
$aClean[$aKeys[$i]] = trim(strip_tags($_REQUEST[$aKeys[$i]]));
break;
}
break;
case "a": // array
// store the value if it is an array
if(is_array($_REQUEST[$aKeys[$i]]))
$aClean[$aKeys[$i]] = $_REQUEST[$aKeys[$i]];
break;
default:
// type not recognized, skip it
break;
}
}
/* null out all input data so we can be assured that */
/* no unfiltered values are being used */
$_REQUEST = array();
$_POST = array();
$_GET = array();
if(APPDB_DONT_CLEAR_COOKIES_VAR != "1")
$_COOKIES = array();
return null;
}
?>

15
include/footer.php Normal file
View File

@@ -0,0 +1,15 @@
<!-- End Content -->
</div>
<b class="rbottom"><b class="r4"></b><b class="r3"></b><b class="r2"></b><b class="r1"></b></b>
</div>
</div>
<div id="footer">
Hosted By
<a href="http://www.codeweavers.com/"><img src="<?php echo BASE; ?>images/cw_logo_sm.png" alt="CodeWeavers"
title="CodeWeavers - Run Windows applications and games on Mac and Linux"></a>
</div>
</body>
</html>

42
include/form_edit.php Normal file
View File

@@ -0,0 +1,42 @@
<?php
require_once(BASE."include/util.php");
/*********************/
/* Edit Account Form */
/*********************/
// returns an array of TableRow instances
function GetEditAccountFormRows($sUserEmail, $sUserRealname)
{
$aTableRows = array();
$oTableRow = new TableRow();
$oTableRow->AddTextCell("&nbsp; Email Address");
$oTableRow->AddTextCell('<input type="text" name="sUserEmail" '.
'value="'.$sUserEmail.'">');
$aTableRows[] = $oTableRow;
$oTableRow = new TableRow();
$oTableRow->AddTextCell("&nbsp; Password");
$oTableRow->AddTextCell('<input type="password" name="sUserPassword">');
$aTableRows[] = $oTableRow;
$oTableRow = new TableRow();
$oTableRow->AddTextCell("&nbsp; Password (again)");
$oTableRow->AddTextCell('<input type="password" name="sUserPassword2">');
$aTableRows[] = $oTableRow;
$oTableRow = new TableRow();
$oTableRow->AddTextCell("&nbsp; Real Name");
$oTableRow->AddTextCell('<input type="text" name="sUserRealname" value="'.$sUserRealname.'">');
$aTableRows[] = $oTableRow;
$oTableRow = new TableRow();
$oTableRow->AddTextCell("&nbsp;");
$oTableRow->AddTextCell("&nbsp;");
$aTableRows[] = $oTableRow;
return $aTableRows;
}
?>

63
include/form_login.php Normal file
View File

@@ -0,0 +1,63 @@
<?php
require_once(BASE."include/util.php");
/**************/
/* Login Form */
/**************/
echo "<div class='default_container'>\n";
echo '<form method="post" name="sFlogin" action="account.php">',"\n";
echo html_frame_start("Login to Application DB","400","",0);
/* Pass on the URL we should return to after log-in */
global $aClean;
echo '<input type="hidden" name="sReturnTo" value="' . (isset($aClean['sReturnTo']) ? $aClean['sReturnTo'] : '') . '">';
?>
<!-- start of login form -->
<script type="text/javascript">
<!--
function cmd_send_passwd() {
document.sFlogin.sCmd.value = "send_passwd";
document.sFlogin.submit();
}
//-->
</script>
<table border="0" width="100%" cellspacing=0 cellpadding="10">
<tr>
<td class=color1> E-mail </td>
<td class=color0> <input type="text" name="sUserEmail" value='<?php if(!empty($aClean['sUserEmail'])) echo $aClean['sUserEmail']?>'> </td>
</tr>
<tr>
<td class=color1> Password </td>
<td class=color0> <input type="password" name="sUserPassword"> </td>
</tr>
<tr>
<td colspan=2 align=center class=color3>
<input type="submit" name="sLogin" value=" Login " class=button>
</td>
</tr>
</table>
<!-- end of login form -->
<?php
echo html_frame_end("&nbsp;");
echo '<input type="hidden" name="sCmd" value="do_login">',"\n";
echo '<input type="hidden" name="sExtReferer" value="'.$_SERVER['HTTP_REFERER'].'">',"\n";
echo '</form>',"\n";
echo "</div>\n";
?>
<p align=center>Don't have an account yet?<br>
[<a href="account.php?sCmd=new" onMouseOver="document.status='';return true;">Create a New Account</a>]</p>
<p align=center>Lost your password?<br>
[<a href="javascript:cmd_send_passwd();" onMouseOver="document.status='';return true;">Email a New Password</a>]</p>
<?php
echo p(),p(),p();
?>

49
include/form_new.php Normal file
View File

@@ -0,0 +1,49 @@
<?php
require_once(BASE."include/util.php");
/********************/
/* New Account Form */
/********************/
echo "<div class='default_container'>\n";
echo '<form method="post" action="account.php">',"\n";
echo html_frame_start("Create New Application DB Account","400","",0)
?>
<!-- start of new account form -->
The password will be sent to your e-mail
<table border=0 width="100%" cellspacing=0 cellpadding=20>
<tr>
<td class=color1> E-mail </td>
<td class=color0> <input type="text" name="sUserEmail" value='<?php if(!empty($aClean['sUserEmail'])) echo $aClean['sUserEmail']?>'> </td>
</tr>
<tr>
<td class=color1> Real Name </td>
<td class=color0> <input type="text" name="sUserRealname" value='<?php if(!empty($aClean['sUserRealname'])) echo $aClean['sUserRealname']?>'> </td>
</tr>
<?php
echo "<tr><td class=color1>&nbsp; Wine version </td><td class=color0>";
echo make_bugzilla_version_list("sWineRelease", isset($aClean['sWineRelease']) ? $aClean['sWineRelease'] : '');
echo "</td></tr>";
?>
<tr>
<td colspan=2 align=center class=color3>
<input type="submit" name="sCreate" value=" Create Account " class=button>
</td>
</tr>
</table>
<!-- end of new account form -->
<?php
echo html_frame_end("&nbsp;");
echo '<input type="hidden" name="sCmd" value="do_new">',"\n";
echo '</form>',"\n";
echo "</div>\n";
echo p(),p(),p();
?>

61
include/header.php Normal file
View File

@@ -0,0 +1,61 @@
<?php
/*********************************/
/* Application Database - Header */
/*********************************/
?><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>WineHQ <?php echo $title; ?></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta HTTP-EQUIV="Expires" CONTENT="Mon, 06 Jan 1990 00:00:01 GMT">
<meta HTTP-EQUIV="Pragma" CONTENT="no-cache">
<meta name="description" content="Open Source Software for running Windows applications on other operating systems.">
<meta name="keywords" content="windows, linux, macintosh, solaris, freebsd">
<meta name="robots" content="index, follow">
<meta name="copyright" content="Copyright WineHQ.org All Rights Reserved.">
<meta name="language" content="English">
<meta name="revisit-after" content="1">
<link rel="stylesheet" href="<?php echo BASE; ?>styles.css" type="text/css" media="screen">
<script language="JavaScript" src="<?php echo BASE; ?>jquery.js" type="text/javascript"></script>
<script language="JavaScript" src="<?php echo BASE; ?>utils.js" type="text/javascript"></script>
<link rel="stylesheet" href="<?php echo BASE; ?>apidb.css" type="text/css">
<link rel="stylesheet" href="<?php echo BASE; ?>application.css" type="text/css">
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js"></script>
<script src="<?php echo BASE; ?>scripts.js" type="text/javascript"></script>
<link rel="icon" type="image/png" href="<?php echo BASE; ?>images/winehq_logo_16.png">
<link rel="shortcut icon" type="image/png" href="<?php echo BASE; ?>images/winehq_logo_16.png">
</head>
<body>
<div id="logo_glass"><a href="<?php echo BASE; ?>"><img src="<?php echo BASE; ?>images/winehq_logo_glass_sm.png" alt=""></a></div>
<div id="logo_text"><a href="<?php echo BASE; ?>"><img src="<?php echo BASE; ?>images/winehq_logo_text.png" alt="WineHQ" title="WineHQ"></a></div>
<div id="logo_blurb"><?php echo preg_replace("/^ - /", "", $title); ?></div>
<div id="search_box">
<form action="http://www.winehq.org/search" id="cse-search-box" style="margin: 0; padding: 0;">
<input type="hidden" name="cx" value="partner-pub-0971840239976722:w9sqbcsxtyf">
<input type="hidden" name="cof" value="FORID:10">
<input type="hidden" name="ie" value="UTF-8">
<span style="color: #ffffff;">Search:</span> <input type="text" name="q" size="20">
</form>
<script type="text/javascript" src="http://www.google.com/coop/cse/brand?form=cse-search-box&amp;lang=en"></script>
</div>
<div id="tabs">
<ul>
<li><a href="http://www.winehq.org/">WineHQ</a></li>
<li><a href="http://wiki.winehq.org/">Wiki</a></li>
<li class="s"><a href="http://appdb.winehq.org/">AppDB</a></li>
<li><a href="http://bugs.winehq.org/">Bugzilla</a></li>
<li><a href="http://forums.winehq.org/">Forums</a></li>
</ul>
</div>
<div id="main_content">
<div class="rbox">
<b class="rtop"><b class="r1"></b><b class="r2"></b><b class="r3"></b><b class="r4"></b></b>
<div class="content" style="padding: 20px 20px 10px 80px">
<!-- Start Content -->

340
include/html.php Normal file
View File

@@ -0,0 +1,340 @@
<?php
$_indent_level = 0;
function do_indent($str, $v = 0)
{
global $_indent_level;
if($v < 0)
$_indent_level += $v;
if($_indent_level > 0)
$str = str_repeat(" ", $_indent_level) . $str;
if($v > 0)
$_indent_level += $v;
return $str . "\n";
}
function do_html_tr($t, $arr, $class, $extra)
{
if(strlen($class))
$class = " class=\"$class\"";
/* $extra contains parameters to <tr>, such as valign="top" */
if(strlen($extra))
$extra = " $extra";
$str = do_indent("<tr$class$extra>", 1);
for($i = 0; $i < sizeof($arr); $i++)
{
/* If it is not an array, it contains the entire table cell. If it
is an array, [0] holds the main content and [1] the options like
valign="top" */
if(is_array($arr[$i]))
{
$val = $arr[$i][0];
$extra = " ".$arr[$i][1];
}
else
{
$val = $arr[$i];
$extra = "";
}
if (! $val)
{
$val = "&nbsp;";
}
if(stristr($val, "<$t"))
{
$str .= do_indent($val);
}
else
{
$str .= do_indent("<$t$class$extra> ".trim($val)." </$t>", 0);
}
}
$str .= do_indent("</tr>", -1);
return $str;
}
// HTML TR
function html_tr($arr, $class = "", $extra = "")
{
return do_html_tr("td", $arr, $class, $extra);
}
// HTML TABLE
function html_table_begin($extra = "")
{
return do_indent("<table $extra>", 1);
}
function html_table_end()
{
return do_indent("</table>", -1);
}
// HTML HTML
function html_begin()
{
return do_indent("<html>", 1);
}
function html_end()
{
return do_indent("</html>", -1);
}
// HTML HEAD
function html_head($title, $stylesheet = 0)
{
$str = do_indent("<head>", 1);
$str .= do_indent("<title> $title </title>", 0);
if($stylesheet)
$str .= do_indent("<link rel=\"stylesheet\" ".
"href=\"$stylesheet\" type=\"text/css\">", 0);
$str .= do_indent("</head>", -1);
return $str;
}
// HTML BODY
function html_body_begin()
{
return do_indent("<body>", 1);
}
function html_body_end()
{
return do_indent("</body>", -1);
}
// HTML A HREF
function html_ahref($label, $url, $extra = "")
{
$label = stripslashes($label);
if (!$label and $url)
{
return do_indent(" <a href=\"$url\" $extra>$url</a> ");
}
else if (!$label)
{
return do_indent(" &nbsp; ");
}
else
{
return do_indent(" <a href=\"$url\" $extra>$label</a> ");
}
}
function html_imagebutton($text, $url, $extra = "")
{
static $i = 1;
$i++;
$img1 = apidb_url("util/button.php?text=".urlencode($text)."&amp;pressed=0");
$img2 = apidb_url("util/button.php?text=".urlencode($text)."&amp;pressed=1");
$java = "onMouseDown = 'document.img$i.src = \"$img2\"; return true;' ";
$java .= "onMouseUp = 'document.img$i.src = \"$img1\"; return true;' ";
return "\n<a href=\"$url\" $extra $java>\n <img src=\"$img1\" name=\"img$i\" alt=\"$text\"> </a>\n";
}
function html_frame_start($title = "", $width = "", $extra = "", $innerPad = 0)
{
if ($width) { $width = 'width="'.$width.'"'; }
$str = '<table '.$width.' border="0" class="mainTable" cellpadding="0" cellspacing="0" align="center">'."\n";
if ($title)
{
$str .= '
<tr><td colspan=3><table width="100%" border=0 cellpadding=0 cellspacing=0>
<tr><td>
<table width="100%" border="0" cellpadding="0" cellspacing="0" class="topMenu">
<tr>
<td width="100%" rowspan="3" align="center"><span class="menuTitle">'.$title.'</span></td>
</tr>
</table>
</td></tr>
</table></td></tr>
';
}
$str .= '
<tr>
<td><img src="'.BASE.'images/blank.gif" width="5" height="1" alt=""></td>
<td width="100%"><table width="100%" border=0 cellpadding=0 cellspacing=0>
<tr><td class=topMenu>
<table width="100%" border=0 cellpadding="'.$innerPad.'" cellspacing="1" '.$extra.'><tr><td class=white>
';
return $str;
}
function html_frame_end($text = "")
{
$str = '
</td></tr></table></td></tr>
</table>
</td>
<td><img src="'.BASE.'images/blank.gif" width="5" height="1" alt=""></td>
</tr>
</table>
<br>
';
return $str;
}
function html_select($name, $values, $default = null, $descs = null)
{
$str = "<select name='$name'>\n";
while(list($idx, $value) = each($values))
{
$desc = $value;
if($descs)
$desc = $descs[$idx];
if($value == $default)
$str .= " <option selected value='$value'>$desc\n";
else
$str .= " <option value='$value'>$desc\n";
}
$str .= "</select>\n";
return $str;
}
function html_back_link($howmany = 1, $url = "")
{
if (!$url)
{
$url = 'javascript:history.back('.$howmany.');';
}
return '<p>&nbsp;&nbsp; <a href="'.htmlentities($url).'">&lt;&lt; Back</a></p>'."\n";
}
function p()
{
return "\n<p>&nbsp;</p>\n";
}
function add_br($text = "")
{
$text = ereg_replace("\n","<br>\n",$text);
return $text;
}
function make_dll_option_list($varname, $dllid = -1)
{
$db = new ApiDB();
echo "<select name='$varname'>\n";
//echo "<option value='ALL'>ALL\n";
$list = $db->get_dll_names();
while(list($name, $id) = each($list))
{
if($dllid == $id)
echo "<option value=$id selected>$name ($id)\n";
else
echo "<option value=$id>$name ($id)\n";
}
echo "</select>\n";
}
function make_inx_option_list($varname, $inx = null)
{
$list = array("yes", "no", "stub", "unknown");
echo "<select name='$varname'>\n";
while(list($idx, $value) = each($list))
{
if($value == $inx)
echo "<option value=$value selected>$value\n";
else
echo "<option value=$value>$value\n";
}
echo "</select>\n";
}
/* Displays a note box */
function html_note($shTitle, $shBody)
{
$shRet = '<div class="note_container">';
$shRet .= '<div class="note_title">';
$shRet .= $shTitle;
$shRet .= '</div>';
$shRet .= '<div class="note_body">';
$shRet .= $shBody;
$shRet .= '</div></div>';
return $shRet;
}
function html_radiobuttons($aIds, $aOptions, $sName, $sDefault = '')
{
$shRet = '';
for($i = 0; $i < sizeof($aIds); $i++)
{
if($aIds[$i] == $sDefault)
$shChecked = ' checked="checked"';
else
$shChecked = '';
$shRet .= '<input type="radio" name="'.$sName.'" value="'.$aIds[$i]."\"$shChecked> " . $aOptions[$i].'<br />';
}
return $shRet;
}
function html_checkbox($sName, $sValue, $shText, $bChecked)
{
if($bChecked)
$sSelected = ' checked="checked"';
else
$sSelected = '';
return "<input type=\"checkbox\" name=\"$sName\" value=\"$sValue\"$sSelected /> $shText\n";
}
function html_checkboxes($sName, $aValues, $aTexts, $aSelected)
{
$shRet = '';
for($i = 0; $i < sizeof($aValues); $i++)
$shRet .= html_checkbox($sName.$i, $aValues[$i], $aTexts[$i], $aSelected[$i]).'<br />';
return $shRet;
}
function html_read_input_series($sName, $aInput, $iCount)
{
$aRet = array();
for($i = 0; $i < $iCount; $i++)
{
$aRet[] = getInput($sName.$i, $aInput);
}
return $aRet;
}
?>

439
include/image.php Normal file
View File

@@ -0,0 +1,439 @@
<?php
/*************************************/
/* image and image_resource classes */
/*************************************/
/**
* Image class for handling screenshot and thumbnail image files.
*/
class Image {
var $sFile; // absolute path from the docroot
var $aDebugLog;
var $oImage;
var $iWidth;
var $iHeight;
var $iType;
/**
* Constructor:
* $sFile is the full path to the image. $this->isLoaded()
* should really be checked after making a new object.
*/
function Image($sPath, $bAbsolutePath=false)
{
/* if $bAbsolutePath is true we should use the $sPath without modification */
/* otherwise use appdb_fullpath() to convert the relative $sPath into a absolute path */
if($bAbsolutePath)
$this->sFile = $sPath;
else /* relative path */
$this->sFile = appdb_fullpath($sPath);
$oInfo = @getimagesize($this->sFile);
if( empty($oInfo) )
{
$this->set_debuglog("Failed to load file ".$this->sFile);
return;
}
switch( $oInfo[2] )
{
case 2:
$oImage = imagecreatefromjpeg($this->sFile);
break;
case 3:
$oImage = imagecreatefrompng($this->sFile);
break;
default;
$this->set_debuglog("Image type ({$oInfo[2]}) unknown");
return;
return;
}
$this->oImage = $oImage;
$this->iWidth = $oInfo[0];
$this->iHeight = $oInfo[1];
$this->iType = $oInfo[2];
$this->set_debuglog("New image class created with as $this->sFile as"
." file and {$oInfo[2]} as type. Dimensions"
." {$oInfo[0]}x{$oInfo[1]}");
}
/**
* isLoaded()
* This function should always be checked after loading a file
* with the constructor. Returns true if the image has been
* successfully loaded.
*/
function isLoaded()
{
if($this->iWidth > 0 AND $this->iHeight > 0)
return true;
else
return false;
}
/**
* Returns the latest debug log made for the last function. If $bFull is
* set it will return the full log as array of the object.
*/
function get_debuglog($bFull = 0)
{
if($bFull)
return $this->aDebugLog;
else
return end($this->aDebugLog);
}
function get_width()
{
return $this->iWidth;
}
function get_height()
{
return $this->iHeight;
}
/**
* Returns the image resource identifier.
*/
function get_image_resource()
{
return $this->oImage;
}
/**
* make_thumb()
*
* Calculates resize based on one parameter and calculates the other
* with the right aspect ratio. If you want to use $iNewHeight set
* $iNewWidth to 0.
*
* If none are set APPDB_THUMBNAIL_WIDTH is used. If both are set
* $iNewWidth is used.
*
* If you want to make a border, look at resize_image_border() comment
* and set $iBorderWidth and $sBorderColor as appropriate.
*
*/
function make_thumb($iNewWidth, $iNewHeight, $iBorderWidth = 0, $sBorderColor = '')
{
if($iNewWidth == 0 AND $iNewHeight == 0)
{
$iNewWidth = APPDB_THUMBNAIL_WIDTH;
$iNewHeight = $this->calculate_proportions($this->iWidth, $this->iHeight,$iNewWidth);
}
else if($iNewWidth > 0)
{
$iNewHeight = $this->calculate_proportions($this->iWidth, $this->iHeight,$iNewWidth);
}
else if($iNewHeight > 0)
{
$iNewWidth = $this->calculate_proportions($this->iWidth, $this->iHeight, 0, $iNewHeight);
}
$this->set_debuglog("Resizing image to $iNewWidth x $iNewHeight");
if(!empty($sBorderColor) and $iBorderWidth > 0)
$this->resize_image_border($sBorderColor,$iBorderWidth,$iNewHeight,$iNewWidth);
else
$this->resize_image($iNewWidth,$iNewHeight);
}
/**
* make_full()
*
* Function will make sure your image is as big or smaller than the sizes
* set here with $max_width and $max_height. Aspect ratio will be mantained.
*
* If none are set APPDB_SCREENSHOT_MAXWIDTH and APPDB_SCREENSHOT_MAXHEIGHT
* are used.
*/
function make_full($iMaxWidth = 0, $iMaxHeight = 0)
{
if(!$iMaxWidth > 0)
$iMaxWidth = APPDB_SCREENSHOT_MAXWIDTH;
if(!$iMaxHeight > 0)
$iMaxHeight = APPDB_SCREENSHOT_MAXHEIGHT;
if($this->iWidth > $iMaxWidth)
{
/* The width is too much */
$iNewWidth = $iMaxWidth;
$iNewHeight = $this->calculate_proportions($this->iWidth,$this->iHeight,$iNewWidth);
/* Check if the height is also within the limits */
if($iNewHeight > $iMaxHeight )
{
$iNewWidth = $this->calculate_proportions($iNewWidth,$iNewHeight,0,$iMaxHeight);
$iNewHeight = $iMaxHeight;
}
}
else if($this->iHeight > $iMaxHeight)
{
/* Width was ok, height not */
$iNewWidth = $this->calculate_proportions($this->iWidth,$this->iHeight,0,$iMaxHeight);
$iNewHeight = $iMaxHeight;
}
else
{
/* All ok */
$iNewWidth = $this->iWidth;
$iNewHeight = $this->iHeight;
}
$this->set_debuglog("Resizing image to $iNewWidth x $iNewHeight");
$this->resize_image($iNewWidth, $iNewHeight);
}
/**
* resize_image()
*
* Resizes the image with the width and height specified with
* $iNewHeight and $iNewWidth.
*/
function resize_image($iNewWidth, $iNewHeight)
{
// GD 2.x
if(function_exists("imagecreatetruecolor"))
{
$oNewImage = imagecreatetruecolor($iNewWidth, $iNewHeight);
imagecopyresampled($oNewImage,$this->oImage,0,0,0,0,
$iNewWidth,$iNewHeight,$this->iWidth,$this->iHeight);
} else // GD 1.x
{
$oNewImage = imagecreate($iNewWidth, $iNewHeight);
imagecopyresized($oNewImage,$this->oImage,0,0,0,0,
$iNewWidth,$iNewHeight,$this->iWidth,$this->iHeight);
}
$this->set_debuglog("imagecopyresized($oNewImage,$this->oImage,0,0,0,0,$iNewWidth,"
."$iNewHeight,$this->iWidth,$this->iHeight);");
imagedestroy($this->oImage);
$this->oImage = $oNewImage;
$this->iWidth = $iNewWidth;
$this->iHeight= $iNewHeight;
}
/**
* resize_image_border()
*
* Resizes the image. With the $iNewWidth + $iBorderWidth*2
* and $iNewHeight + $iBorderWidth*2 as size. $sBorderColor is a
* HTML hexadecimal color (like #0000FF)
*/
function resize_image_border($sBorderColor, $iBorderWidth, $iNewHeight, $iNewWidth)
{
$r = hexdec(substr($sBorderColor, 1, 2));
$g = hexdec(substr($sBorderColor, 3, 2));
$b = hexdec(substr($sBorderColor, 5, 2));
/* We multiply the border width by two because there are borders
on both sides */
// GD 2.x
if(function_exists("imagecreatetruecolor"))
{
$new = imagecreatetruecolor($iNewWidth + ($iBorderWidth*2), $iNewHeight + ($iBorderWidth*2));
} else // GD 1.x
{
$new = imagecreate($iNewWidth + ($iBorderWidth*2), $iNewHeight + ($iBorderWidth*2));
}
/* Make the border by filling it completely,
later on we will overwrite everything except the border */
$color = ImageColorAllocate( $new, $r, $g, $b );
imagefill($new,0,0,$color);
// GD 2.x
if(function_exists("imagecopyresampled"))
{
imagecopyresampled($new,$this->oImage,$iBorderWidth,$iBorderWidth,
0,0, $iNewWidth,$iNewHeight,
$this->iWidth,$this->iHeight);
} else // GD 1.x
{
imagecopyresized($new,$this->oImage,$iBorderWidth,$iBorderWidth,
0,0,$iNewWidth,$iNewHeight,
$this->iWidth,$this->iHeight);
}
$this->set_debuglog("imagecopyresized($new,$this->oImage,$iBorderWidth,$iBorderWidth,0,0,"
." $iNewWidth,$iNewHeight,$this->iWidth,$this->iHeight); with a $iBorderWidth px border"
." in $sBorderColor");
imagedestroy($this->oImage);
$this->oImage = $new;
$this->iWidth = $iNewWidth;
$this->iHeight= $iNewHeight;
}
/**
* add_watermark()
*
* $watermark is an image resource identifier to any image resource.
*
* $min_mark_wwidth and $min_mark_height are the minimum sizes of the
* destination image before the watermark is added. If none are set
* both will be 0.
*
* A warning for transparency. If you resize an image down with make_thumb()
* you loose the transparency on png images.
*/
function add_watermark($oWatermark, $iMinMarkWidth = 0, $iMinMarkHeight = 0)
{
$iWatermarkWidth = imagesx($oWatermark);
$iWatermarkHeight = imagesy($oWatermark);
if($this->iWidth > $iMinMarkWidth AND
$this->iHeight > $iMinMarkHeight)
{
$iWatermark_x = $this->iWidth - $iWatermarkWidth;
$iWatermark_y = $this->iHeight - $iWatermarkHeight;
imagecopy($this->oImage, $oWatermark, $iWatermark_x, $iWatermark_y,
0, 0, $iWatermarkWidth, $iWatermarkHeight);
$this->set_debuglog("imagecopy($this->oImage, $oWatermark,"
."$iWatermark_x, $iWatermark_y, 0, 0,"
."$iWatermarkWidth, $iWatermarkHeight);");
}
}
/**
* Save the image to a file set with $store.
*
* $iType is optional and is set like the second index of getimagesize().
* If none (or 0) is set the original type of the file is used.
* If $store is not give, the current file name will be used.
* $quality is the jpeg output quality (100 best, 0 worst). Default is 75
*/
function output_to_file($sOutputFilename=null, $iType = 0, $iQuality = 75)
{
if(!$sOutputFilename)
$sOutputFilename = $this->sFile;
if($iType == 0)
$iType = $this->iType;
switch($iType)
{
case 2:
imagejpeg($this->oImage, $sOutputFilename, $iQuality);
$this->set_debuglog("Saved file as jpeg to $sOutputFilename");
break;
case 3:
imagepng($this->oImage, $sOutputFilename);
$this->set_debuglog("Saved file as png to $sOutputFilename");
break;
default:
$this->set_debuglog("Unknown output type");
return;
}
return true;
}
/**
* Output the files to the browser.
*
* If $bHeader is true a Content-type header with the correct type
* is set.
* $iType is optional and is set like the second index of getimagesize().
* If none (or 0) is set the original type of the file is used.
*
* $iQuality is the jpeg output quality (100 best, 0 worst)
*/
function output_to_browser($bHeader, $iType = 0, $iQuality = 75)
{
if($iType == 0 )
$iType = $this->iType;
switch($iType)
{
case 2:
if($bHeader)
header('Content-type: image/jpeg');
imagejpeg($this->oImage,'',$iQuality);
$this->set_debuglog("Outputed file as jpeg to browser");
break;
case 3:
if($bHeader)
header('Content-type: image/png');
imagepng($this->oImage);
$this->set_debuglog("Outputed file as png to browser");
break;
default:
$this->set_debuglog("Unknown output type");
}
}
/**
* Destroys the image resource. Be sure to do this at the end of your
* actions with this object.
*/
function destroy()
{
if(is_resource($this->oImage))
imagedestroy($this->oImage);
}
/**
* Deletes the screenshot from the file system.
*/
function delete()
{
// if the file exists, delete it
if(is_file($this->sFile))
unlink($this->sFile);
}
/***********************
* PRIVATE FUNCTIONS
************************/
function set_debuglog( $sLog )
{
$this->aDebugLog[] = $sLog;
}
function calculate_proportions($iWidth, $iHeight,
$iNewWidth, $iNewHeight = '0')
{
if($iNewWidth > 0)
// we want to calculate the new height
return ($iHeight * $iNewWidth) / $iWidth;
else if( $iNewHeight > 0 )
return ($iWidth * $iNewHeight) / $iHeight;
else
return 0;
}
}
class ImageResource extends Image {
function ImageResource($oImage,$iType)
{
$this->oImage = $oImage;
$this->iWidth = imagesx($oImage);
$this->iHeight = imagesy($oImage);
$this->iType = $iType;
$this->set_debuglog("New image class created with $oImage as"
." image resource and $iType as type. Dimensions"
." {$this->iWidth}x{$this->iHeight}");
}
}
?>

301
include/incl.php Normal file
View File

@@ -0,0 +1,301 @@
<?php
/*************************************************/
/* Main Include Library for Application Database */
/*************************************************/
// get modules
ini_set("memory_limit","64M");
require_once(BASE."include/config.php");
require(BASE."include/util.php");
require(BASE."include/user.php");
require(BASE."include/session.php");
require(BASE."include/menu.php");
require(BASE."include/html.php");
require(BASE."include/error_log.php");
require(BASE."include/query.php");
require(BASE."include/table.php");
require_once(BASE."include/objectManager.php");
/* if magic quotes are enabled make sure the user disables them */
/* otherwise they will see all kinds of odd effects that are difficult */
/* to track down */
if(get_magic_quotes_gpc())
{
echo "<b>Please disable the magic quotes GPC PHP setting. See <a href=\"http://us2.php.net/manual/en/ref.info.php#ini.magic-quotes-gpc\"> this page</a> for more information</b><br><br>";
echo "AppDB php code assumes magic quotes are disabled.<br><br>";
echo "Magic quotes are a bad idea for a few reasons.<br><br>";
echo "First is that php calls <b>addslashes()</b> on all \$_POST, \$_REQUEST and cookie variables ";
echo "if magic quotes is enabled. ";
echo "Ooooooh you say.<br>";
echo "<i>\"Aren't magic quotes a convienent way to protect my php code from sql injection attacks?\"</i><br><br>";
echo "No! <b>addslashes()</b> isn't adequate. You should use <b>query_escape_string()</b> or some other function";
echo " that will handle multi-byte characters. See <a href=\"http://shiflett.org/archive/184\">this article</a>";
echo " for a way to exploit <b>addslash()</b>ed parameters.<br><br>";
echo "A second reason is that with magic quotes enabled, due to the use of <b>query_escape_string()</b> to";
echo " protect from sql injection attacks we'll end up with variables that have been addslash()ed and";
echo " <b>query_escape_string()</b>ed. So you end up having to call stripslashes() on EVERY variable. ";
exit;
}
/**
* rename $_REQUEST variables to preserve backwards compatibility
* with bugzilla links and urls in emails and on google from before our
* mass rename of GPC variables to use our coding standard prefixing
*
* NOTE: we may be able to remove these backwareds compatibility changes
* in a few years, check in mid 2007 to see how many old
* links are still poping up in google then
*/
if(isset($_REQUEST['versionId']))
{
$_REQUEST['iVersionId'] = $_REQUEST['versionId'];
unset($_REQUEST['versionId']);
}
if(isset($_REQUEST['appId']))
{
$_REQUEST['iAppId'] = $_REQUEST['appId'];
unset($_REQUEST['appId']);
}
if(isset($_REQUEST['bug_id']))
{
$_REQUEST['iBugId'] = $_REQUEST['bug_id'];
unset($_REQUEST['bug_id']);
}
if(isset($_REQUEST['catId']))
{
$_REQUEST['iCatId'] = $_REQUEST['catId'];
unset($_REQUEST['catId']);
}
if(isset($_REQUEST['sub']))
{
$_REQUEST['sSub'] = $_REQUEST['sub'];
unset($_REQUEST['sub']);
}
if(isset($_REQUEST['topic']))
{
$_REQUEST['sTopic'] = $_REQUEST['topic'];
unset($_REQUEST['topic']);
}
if(isset($_REQUEST['mode']))
{
$_REQUEST['sMode'] = $_REQUEST['mode'];
unset($_REQUEST['mode']);
}
/* End backwards compatibility code */
// create arrays
$sidebar_func_list = array();
$help_list = array();
function apidb_help_add($desc, $id)
{
global $help_list;
$help_list[] = array($desc, $id);
}
// return url with docroot prepended
function apidb_url($path)
{
return BASE.$path;
}
// return FULL url with docroot prepended
function apidb_fullurl($path = "")
{
return BASE.$path;
}
function appdb_fullpath($path)
{
/* IE: we know this file is in /yyy/xxx/include, we want to get the /yyy/xxx
/* so we call dirname on this file path twice */
$fullpath = dirname(dirname(__FILE__))."//".$path;
/* get rid of potential double slashes due to string concat */
return str_replace("//", "/", $fullpath);
}
/*
* output the common apidb header
*/
function apidb_header($title = 0)
{
$realname = $_SESSION['current']->sRealname;
// Set Page Title
$page_title = $title;
if ($title)
$title = " - $title";
// grab the starting time
global $sPageGeneratingStartTime;
$sPageGeneratingStartTime = microtime();
$aStartarray = explode(" ", $sPageGeneratingStartTime);
$sPageGeneratingStartTime = $aStartarray[1] + $aStartarray[0];
// Display Header
include(BASE."include/header.php");
// Display Sidebar
apidb_sidebar();
// Display Status Messages
dumpmsgbuffer();
}
/*
* output the common apidb footer
*/
function apidb_footer()
{
// grab the end of the page generating time
global $sPageGeneratingStartTime;
$sPageGeneratingEndTime = microtime();
$aEndarray = explode(" ", $sPageGeneratingEndTime);
$sPageGeneratingEndTime = $aEndarray[1] + $aEndarray[0];
$sTotaltime = $sPageGeneratingEndTime - $sPageGeneratingStartTime;
$sTotaltime = round($sTotaltime,5);
echo "<center>Page loaded in <b>$sTotaltime</b> seconds.</center>";
// Display Footer
if(!isset($header_disabled))
include(BASE."include/"."footer.php");
}
/*
* output the sidebar, calls all functions registered with apidb_sidebar_add
*/
function apidb_sidebar()
{
global $sidebar_func_list;
echo '
<div id="sidebar">
<ul>
';
//TURN on GLOBAL ADMIN MENU
if ($_SESSION['current']->hasPriv("admin"))
{
include(BASE."include/sidebar_admin.php");
apidb_sidebar_add("global_admin_menu");
} else if($_SESSION['current']->isMaintainer()) /* if the user maintains anything, add their menus */
{
include(BASE."include/sidebar_maintainer_admin.php");
apidb_sidebar_add("global_maintainer_admin_menu");
}
// Login Menu
include(BASE."include/sidebar_login.php");
apidb_sidebar_add("global_sidebar_login");
// Main Menu
include(BASE."include/sidebar.php");
apidb_sidebar_add("global_sidebar_menu");
//LOOP and display menus
for($i = 0; $i < sizeof($sidebar_func_list); $i++)
{
$func = $sidebar_func_list[$i];
$func();
}
echo '
</ul>
</div>
';
}
/**
* register a sidebar menu function
* the supplied function is called when the sidebar is built
*/
function apidb_sidebar_add($funcname)
{
global $sidebar_func_list;
array_unshift($sidebar_func_list, $funcname);
}
function apidb_image($name)
{
return BASE."images/$name";
}
/**
* format a date as required for HTTP by RFC 2068 sec 3.3.1
*/
function fHttpDate($iDate) {
return gmdate("D, d M Y H:i:s",$iDate)." GMT";
}
/**
* parse all the date formats required by HTTP 1.1 into PHP time values
*/
function pHttpDate($sDate) {
$iDate = strtotime($sDate);
if ($iDate != -1) return $iDate;
/* the RFC also requires asctime() format... */
$aTs = strptime($sDate,"%a %b %e %H:%M:%S %Y");
$iDate = gmmktime($aTs[2],$aTs[1],$aTs[0],$aTs[4],$aTs[3],$aTs[5],0);
return $iDate;
}
/**
* msgs will be displayed on the Next page view of the same user
*/
function addmsg($shText, $color = "black")
{
$GLOBALS['session']->addmsg($shText, $color);
}
function purgeSessionMessages()
{
$GLOBALS['session']->purgemsg();
}
/**
* output msg_buffer and clear it.
*/
function dumpmsgbuffer()
{
$GLOBALS['session']->dumpmsgbuffer();
if (is_array($GLOBALS['session']->msg) and count($GLOBALS['session']->msg) > 0)
{
echo html_frame_start("","300","",5);
foreach ($GLOBALS['session']->msg as $msg)
{
if ($msg['color'] == "red")
$msg['color'] = "{$msg['color']}; text-decoration: blink;";
echo "<div align=\"center\" class=\"session_note\" style=\"color: {$msg['color']};\"> {$msg['msg']} </div>";
}
echo html_frame_end("&nbsp;");
echo "<br>\n";
}
}
/**
* Init Session (stores user info in session)
*/
$session = new session("whq_appdb");
$session->register("current");
if(!isset($_SESSION['current']))
{
$_SESSION['current'] = new User();
}
// if we are debugging we need to see all errors
if($_SESSION['current']->showDebuggingInfos()) error_reporting(E_ALL ^ E_NOTICE);
// include filter.php to filter all REQUEST input
require(BASE."include/filter.php");
?>

48
include/mail.php Normal file
View File

@@ -0,0 +1,48 @@
<?php
require_once(BASE."include/config.php");
function mail_appdb($sEmailList,$sSubject,$sMsg)
{
// NOTE: For AppDB developers: If email is disabled return from this function
// immediately. See include/config.php.sample for information
if(defined("DISABLE_EMAIL"))
return;
$sEmailListComma = str_replace(" ",",",$sEmailList);
$sHeaders = "MIME-Version: 1.0\r\n";
$sHeaders .= "From: AppDB <".APPDB_SENDER_EMAIL.">\r\n";
$sHeaders .= "Reply-to: AppDB <".APPDB_SENDER_EMAIL.">\r\n";
$sHeaders .= "Bcc: $sEmailListComma\r\n";
$sHeaders .= "X-Priority: 3\r\n";
$sHeaders .= "X-Mailer: ".APPDB_OWNER." mailer\r\n";
$sMsg = trim(ereg_replace("\r\n","\n",$sMsg));
$sMsg = $sSubject."\n-------------------------------------------------------\n".$sMsg."\n\n";
$sMsg .= "Best regards.\n";
$sMsg .= "The AppDB team\n";
$sMsg .= APPDB_ROOT."\n";
$sMsg .= "\n\nIf you don't want to receive any other e-mail, please change your preferences:\n";
$sMsg .= APPDB_ROOT."preferences.php\n";
/* Print the message to the screen instead of sending it, if the PRINT_EMAIL
option is set. Output in purple to distinguish it from other messages */
if(defined("PRINT_EMAIL"))
{
$sMsg = str_replace("\n", "<br>", $sMsg);
addmsg("This mail would have been sent<br><br>".
"To: $sEmailList<br>".
"Subject: $sSubject<br><br>".
"Body:<br>$sMsg", "purple");
return;
}
$sMsg = html_entity_decode($sMsg);
$bResult = mail(APPDB_SENDER_EMAIL, "[AppDB] ".$sSubject, $sMsg, $sHeaders,
"-f".APPDB_SENDER_EMAIL);
if($bResult)
addmsg("E-mail sent", "green");
else
addmsg("Error while sending e-mail", "red");
return $bResult;
}
?>

1414
include/maintainer.php Normal file

File diff suppressed because it is too large Load Diff

151
include/maintainerView.php Normal file
View File

@@ -0,0 +1,151 @@
<?php
/**
* Class to show an overview of a user's maintainership, including apps maintained
* and their ratings
*/
class maintainerView
{
var $iUserId;
var $bViewingSelf;
function maintainerView($iUserId = null)
{
if(!$iUserId)
$this->iUserId = $_SESSION['current']->iUserId;
else
$this->iUserId = $iUserId;
if(!$iUserId || $this->iUserId == $_SESSION['current']->iUserId)
$this->bViewingSelf = true;
else
$this->bViewingSelf = false;
}
function objectGetId()
{
return $this->iUserId;
}
/* We don't queue this class or process it in any way */
function objectGetState()
{
return 'accepted';
}
function addVersionRatingInfo($oTableRow, $oVersion)
{
$oTableRow->AddTextCell($oVersion->objectMakeLink());
/* Rating info */
$oTableCell = new TableCell($oVersion->sTestedRating);
$oTableCell->SetClass($oVersion->sTestedRating);
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell($oVersion->sTestedRelease);
$oTableCell->SetClass($oVersion->sTestedRating);
$oTableRow->AddCell($oTableCell);
/* Get test reports submitted by the user */
$aTestData = testData::getTestResultsForUser($this->iUserId,
$oVersion->iVersionId);
if(sizeof($aTestData))
{
$oTest = $aTestData[0];
$sUserRating = $oTest->sTestedRating;
$sUserRelease = $oTest->sTestedRelease;
} else
{
$sUserRating = '';
$sUserRelease = '';
}
$oTableCell = new TableCell($sUserRating);
$oTableCell->SetClass($sUserRating);
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell($sUserRelease);
$oTableCell->SetClass($sUserRating);
$oTableRow->AddCell($oTableCell);
return $oTableRow;
}
/* Shows a detailed vis of the user's maintained applications,
including last tested release & rating */
function display()
{
$oUser = new user($this->iUserId);
$aMaintainedApps = maintainer::getAppsMaintained($oUser);
if(!$aMaintainedApps || !sizeof($aMaintainedApps))
{
if($this->bViewingSelf)
echo '<p>You do not maintain any apps</p>';
else
echo "<p>{$oUser->sRealname} does not maintain any apps</p>";
return;
}
if($this->bViewingSelf)
echo '<p>Viewing your maintained apps</p>';
else
echo "<p>Viewing {$oUser->sRealname}'s maintained apps</p>";
$oTable = new Table();
$oTableRow = new TableRow();
$oTableRow->setClass('color4');
$oTable->setCellSpacing(0);
$oTable->setCellPadding(3);
$oTableRow->AddTextCell('Application');
$oTableRow->AddTextCell('Version');
$oTableRow->AddTextCell('Current Rating');
$oTableRow->AddTextCell('Current Version');
$oTableRow->AddTextCell($this->bViewingSelf ? 'Your Rating' : "User's Rating");
$oTableRow->AddTextCell($this->bViewingSelf ? 'Your Version' : "User's Version");
$oTable->AddRow($oTableRow);
$i = 1;
while(list($iIndex, list($iAppId, $iVersionId, $bSuperMaintainer)) = each($aMaintainedApps))
{
$oApp = new application($iAppId);
$aVersions = array();
$oTableRow = new TableRow();
$oTableRow->AddTextCell($oApp->objectMakeLink());
$oTableRow->SetClass(($i % 2) ? 'color0' : 'color1');
$i++;
if($iVersionId)
{
$oVersion = new version($iVersionId);
$oTableRow = maintainerView::addVersionRatingInfo($oTableRow, $oVersion);
$oTable->AddRow($oTableRow);
} else
{
$aVersions = $oApp->getVersions(true);
$oTableRow->AddTextCell('*');
$oTableRow->AddTextCell('');
$oTableRow->AddTextCell('');
$oTableRow->AddTextCell('');
$oTableRow->AddTextCell('');
$oTable->AddRow($oTableRow);
}
foreach($aVersions as $oVersion)
{
$oTableRow = new TableRow($oTableRow);
$oTableRow->AddTextCell('');
$oTableRow = maintainerView::addVersionRatingInfo($oTableRow, $oVersion);
$oTableRow->SetClass(($i % 2) ? 'color0' : 'color1');
$i++;
$oTable->AddRow($oTableRow);
}
}
echo $oTable->GetString();
}
}
?>

46
include/menu.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
class htmlmenu {
function htmlmenu($name, $form = null)
{
if ($form)
echo "<form action=\"$form\" method=\"post\">\n";
echo '
<li class="top"><p>'.$name.'</p></li>
';
}
/* add a table row */
function add($sName, $shUrl = null, $sAlign = "left")
{
$oTableRow = new TableRow();
if($shUrl)
{
echo " <li><p><a href=\"{$shUrl}\">{$sName}</a></p></li>\n";
}
else
{
echo " <li><p>{$sName}</a></li>\n";
}
}
function addmisc($sStuff, $sAlign = "left")
{
echo "<li><p style=\"text-align: $sAlign\">$sStuff</p></li>\n";
}
function done($form = null)
{
echo '
<li class="bot"></li>
';
if ($form)
echo "</form>\n";
}
}
?>

387
include/monitor.php Normal file
View File

@@ -0,0 +1,387 @@
<?php
/***************************************/
/* Monitor class and related functions */
/***************************************/
/**
* Monitor class for handling Monitors
*/
class Monitor {
var $iMonitorId;
// variables necessary for creating a monitor
var $iAppId;
var $iVersionId;
var $iUserId;
/**
* Constructor.
* If $iMonitorId is provided, fetches Monitor.
*/
function Monitor($iMonitorId="", $oRow = null)
{
if(!$iMonitorId && !$oRow)
return;
if(!$oRow)
{
$sQuery = "SELECT *
FROM appMonitors
WHERE monitorId = '".$iMonitorId."'";
$hResult = query_appdb($sQuery);
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iMonitorId = $oRow->monitorId;
$this->iAppId = $oRow->appId;
$this->iVersionId = $oRow->versionId;
$this->iUserId = $oRow->userId;
}
}
function find($iUserId, $iVersionId=0)
{
if($iUserId && $iVersionId)
{
$sQuery = "SELECT *
FROM appMonitors
WHERE userId = '".$iUserId."'
AND versionId = '".$iVersionId."'";
$hResult = query_appdb($sQuery);
if( $oRow = query_fetch_object($hResult) )
{
$this->iMonitorId = $oRow->monitorId;
$this->iAppId = $oRow->appId;
$this->iVersionId = $oRow->versionId;
$this->iUserId = $oRow->userId;
}
}
}
public function objectGetParent($sClass = '')
{
if($this->iVersionId)
return new version($this->iVersionId);
else
return new application($this->iAppId);
}
public function objectSetParent($iNewId, $sClass = '')
{
if($this->iVersionId)
$this->iVersionId = $iNewId;
else
$this->iAppId = $iNewId;
}
function objectGetChildren($bIncludeDeleted = false)
{
/* We have none */
return array();
}
/*
* Creates a new Monitor.
* Informs interested people about the creation.
* Returns true on success, false on failure
*/
function create()
{
/* Check for duplicate entries */
$oMonitor = new monitor();
$this->iUserId = $_SESSION['current']->iUserId;
$oMonitor->find($this->iUserId, $this->iVersionId);
if($oMonitor->iVersionId)
return FALSE;
// create the new monitor entry
$hResult = query_parameters("INSERT INTO appMonitors (versionId, appId,".
"submitTime, userId) ".
"VALUES ('?', '?', ?, '?')",
$this->iVersionId, $this->iAppId,
"NOW()", $this->iUserId);
if($hResult)
{
$this->Monitor(query_appdb_insert_id());
$sWhatChanged = "New monitor\n\n";
$this->SendNotificationMail("add", $sWhatChanged);
return true;
} else
{
addmsg("Error while creating a new Monitor.", "red");
return false;
}
}
function update()
{
$oMonitor = new monitor($this->iMonitorId);
if($this->iVersionId && $oMonitor->iVersionId != $this->iVersionId)
{
$hResult = query_parameters("UPDATE appMonitors SET versionId = '?'
WHERE monitorId = '?'",
$this->iVersionId, $this->iMonitorId);
if(!$hResult)
return FALSE;
}
if($this->iAppId && $oMonitor->iAppId != $this->iAppId)
{
$hResult = query_parameters("UPDATE appMonitors SET appId = '?'
WHERE monitorId = '?'",
$this->iAppId, $this->iMonitorId);
if(!$hResult)
return FALSE;
}
return TRUE;
}
function unQueue()
{
return true; // We don't queue monitors
}
function objectGetSubmitterId()
{
return $this->iUserId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
$sSubject = null;
$sMsg = null;
if($this->iVersionId)
{
$sWhat = "version";
$sName = version::fullName($this->iVersionId);
$oVersion = new version($this->iVersionId);
$sUrl = $oVersion->objectMakeUrl();
} else
{
$sWhat = "application";
$oApp = new application($this->iAppId);
$sName = $oApp->sName;
$sUrl = $oApp->objectMakeUrl();
}
if($bMailSubmitter)
{
switch($sAction)
{
case "delete":
if($bParentActino)
{
$sSubject = "Monitored $sWhat deleted";
$sMsg = "The $sWhat $sName which you monitored has been ".
"deleted by ".$_SESSION['current']->iUserId.".";
}
break;
}
$aMailTo = null;
} else
{
$oUser = new user($this->iUserId);
$sUser = $oUser->sName;
switch($sAction)
{
case "delete":
if(!$bParentAction)
{
$sSubject = "Monitor for $sName removed: $sUser";
$sMsg = $sUrl;
}
break;
}
User::get_notify_email_address_list(null, $this->iVersionId);
}
return array($sSubject, $sMsg, $aMailTo);
}
function purge()
{
return $this->delete();
}
/**
* Removes the current Monitor from the database.
* Informs interested people about the deletion.
*/
function delete()
{
$hResult = query_parameters("DELETE FROM appMonitors WHERE monitorId = '?'", $this->iMonitorId);
if(!$hResult)
return FALSE;
return TRUE;
}
function SendNotificationMail($sAction="add",$sMsg=null)
{
/* Set variables depending on whether it is an application or version monitor */
if(isset($this->iVersionId))
{
$oVersion = new version($this->iVersionId);
$sAppName = version::fullName($this->iVersionId);
$sUrl = $oVersion->objectMakeUrl();
$sVersion = " version";
} else
{
$oApp = new application($this->iAppId);
$sAppName = Application::lookup_name($this->iAppId);
$sUrl = $oApp->objectMakeUrl();
}
switch($sAction)
{
case "add":
$sSubject = "Monitor for ".$sAppName;
$sSubject .= " added: ".$_SESSION['current']->sRealname;
$sMsg .= "$sUrl\n";
addmsg("You will now receive an email whenever changes are made ".
"to this application$sVersion.", "green");
break;
case "delete":
$sSubject = "Monitor for ".$sAppName;
$sSubject .= " removed: ".$_SESSION['current']->sRealname;
$sMsg .= "$sUrl\n";
addmsg("You will no longer receive an email whenever changes ".
"are made to this application$sVersion.", "green");
break;
}
$sEmail = User::get_notify_email_address_list(null, $this->iVersionId);
if($sEmail)
mail_appdb($sEmail, $sSubject ,$sMsg);
}
function objectGetState()
{
// We don't queue monitors
return 'accepted';
}
function canEdit()
{
if($_SESSION['current']->hasPriv("admin") ||
($this->iUserId == $_SESSION['current']->iUserId))
return TRUE;
return FALSE;
}
function mustBeQueued()
{
return FALSE;
}
/* Stub */
function display()
{
return "";
}
/* Stub */
function getOutputEditorValues($aClean)
{
$this->iVersionId = $aClean['iVersionId'];
$this->iAppId = $aClean['iAppId'];
}
/* Stub */
function objectGetHeader()
{
return null;
}
function objectGetId()
{
return $this->iMonitorId;
}
/* Stub */
function objectGetTableRow()
{
return null;
}
/* Stub */
function objectMakeLink()
{
return "";
}
/* Stub */
function objectMakeUrl()
{
return "";
}
/* Stub */
function outputEditor()
{
return "";
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true)
{
$hResult = query_parameters("SELECT * FROM appMonitors");
if(!$hResult)
return FALSE;
return $hResult;
}
function objectGetEntriesCount($sState)
{
$hResult = query_parameters("SELECT COUNT(DISTINCT monitorId) as count
FROM appMonitors");
if(!$hResult)
return FALSE;
$oRow = query_fetch_object($hResult);
if(!$oRow)
return FALSE;
return $oRow->count;
}
function allowAnonymousSubmissions()
{
/* That makes no sense */
return FALSE;
}
/* Retrieve the user's monitored versions */
function getVersionsMonitored($oUser)
{
$hResult = query_parameters("SELECT appId, versionId FROM appMonitors WHERE userId = '?'", $oUser->iUserId);
if(!$hResult || query_num_rows($hResult) == 0)
return NULL;
$aVersionsMonitored = array();
for($i = 0; $oRow = query_fetch_object($hResult); $i++)
$aVersionsMonitored[$i] = array($oRow->appId, $oRow->versionId);
return $aVersionsMonitored;
}
}
?>

877
include/note.php Normal file
View File

@@ -0,0 +1,877 @@
<?php
require_once(BASE."include/util.php");
require_once(BASE."include/version.php");
/************************************/
/* note class and related functions */
/************************************/
define('APPNOTE_SHOW_FOR_ALL', -1);
define('APPNOTE_SHOW_FOR_VERSIONS', -2);
define('APPNOTE_SHOW_FOR_APP', -3);
define('APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS', -4);
/**
* Note class for handling notes
*/
class Note {
var $iNoteId;
var $iVersionId;
var $iAppId;
var $sTitle;
var $shDescription;
var $iSubmitterId;
var $sSubmitTime;
var $iLinkedWith;
var $aNoteLinks;
/**
* Constructor.
* If $iNoteId is provided, fetches note.
*/
function Note($iNoteId = null, $oRow = null)
{
$this->aNoteLinks = array();
if(!$iNoteId && !$oRow)
return;
if(!$oRow)
{
$sQuery = "SELECT * FROM appNotes WHERE noteId = '?'";
if($hResult = query_parameters($sQuery, $iNoteId))
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iNoteId = $oRow->noteId;
$this->iVersionId = $oRow->versionId;
$this->iAppId = $oRow->appId;
$this->sTitle = $oRow->noteTitle;
$this->shDescription = $oRow->noteDesc;
$this->sSubmitTime = $oRow->submitTime;
$this->iSubmitterId = $oRow->submitterId;
$this->iLinkedWith = $oRow->linkedWith;
$this->aNoteLinks = $this->objectGetChildren();
}
}
/*
* Creates a new note.
* Informs interested people about the creation.
* Returns true on success, false on failure
*/
function create()
{
$hResult = query_parameters("INSERT INTO appNotes (versionId, ".
"appId, noteTitle, noteDesc, submitterId, ".
"submitTime) ".
"VALUES('?', '?', '?', '?', '?', ?)",
$this->iVersionId, $this->iAppId,
$this->sTitle, $this->shDescription,
$_SESSION['current']->iUserId,
"NOW()");
if($hResult)
{
// We need to backup the noteLinks array
$aNoteLinks = $this->aNoteLinks;
$this->note(query_appdb_insert_id());
foreach($aNoteLinks as $oLink)
{
$oLink->objectSetParent($this->iNoteId, 'note');
$this->aNoteLinks[] = $oLink;
}
$this->saveNoteLinks(true);
$sWhatChanged = "Description is:\n".$this->shDescription.".\n\n";
$this->SendNotificationMail("add", $sWhatChanged);
return true;
}
else
{
addmsg("Error while creating a new note.", "red");
return false;
}
}
function unQueue()
{
return true; // We don't queue notes
}
/**
* Update note.
* Returns true on success and false on failure.
*/
function update()
{
$sWhatChanged = "";
/* create an instance of ourselves so we can see what has changed */
$oNote = new Note($this->iNoteId);
if ($this->sTitle && $this->sTitle!=$oNote->sTitle)
{
if (!query_parameters("UPDATE appNotes SET noteTitle = '?' WHERE noteId = '?'",
$this->sTitle, $this->iNoteId))
return false;
$sWhatChanged .= "Title was changed from ".$oNote->sTitle." to ".$this->sTitle.".\n\n";
}
if ($this->shDescription && $this->shDescription!=$oNote->shDescription)
{
if (!query_parameters("UPDATE appNotes SET noteDesc = '?' WHERE noteId = '?'",
$this->shDescription, $this->iNoteId))
return false;
$sWhatChanged .= "Description was changed from\n ".$oNote->shDescription."\n to \n".$this->shDescription.".\n\n";
}
if($this->iVersionId == APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS && (sizeof($this->aNoteLinks) == 1))
{
$oLink = $this->aNoteLinks[0];
$this->iVersionId = $oLink->objectGetParent('version');
$this->iAppId = 0;
$oLink->delete();
}
if (($this->iVersionId || $this->iAppId) && $this->iVersionId!=$oNote->iVersionId)
{
if (!query_parameters("UPDATE appNotes SET versionId = '?' WHERE noteId = '?'",
$this->iVersionId, $this->iNoteId))
return false;
if(!$this->iAppId && !$oNote->iAppId) // Changed version only
{
$sVersionBefore = Version::lookup_name($oNote->iVersionId);
$sVersionAfter = Version::lookup_name($this->iVersionId);
$sWhatChanged .= "Version was changed from ".$sVersionBefore." to ".$sVersionAfter.".\n\n";
} else if(!$this->iAppId) // Moved from app to version
{
$sVersionAfter = Version::fullName($this->iVersionId);
$oApp = new application($oNote->iAppId);
$sOldApp = $oApp->sName;
$sWhatChanged .= "Moved from application $sOldApp to version $sVersionAfter.\n\n";
} else if($oNote->hasRealVersionId()) // Moved from version to app
{
$oApp = new application($this->iAppId);
$sNewApp = $oApp->sName;
$sVersionBefore = version::fullName($oNote->iVersionId);
$sWhatChanged .= "Moved from version $sVersionBefore to application $sNewApp.\n\n";
} else // Change display mode for app note
{
$sOldMode = $oNote->getDisplayModeName();
$sNewMode = $this->getDisplayModeName();
$sWhatChanged .= "Display mode was changed from '$sOldMode' to '$sNewMode'.\n\n";
}
}
if (($this->iAppId || $this->iVersionId) && $this->iAppId!=$oNote->iAppId)
{
if(!query_parameters("UPDATE appNotes SET appId = '?' WHERE noteId = '?'",
$this->iAppId, $this->iNoteId))
return false;
}
$this->saveNoteLinks();
if($sWhatChanged)
$this->SendNotificationMail("edit",$sWhatChanged);
return true;
}
function purge()
{
return $this->delete();
}
/**
* Removes the current note from the database.
* Informs interested people about the deletion.
*
* Returns: true if successful, false if not
*/
function delete()
{
$hResult = query_parameters("DELETE FROM appNotes WHERE noteId = '?'", $this->iNoteId);
if(!$hResult)
return FALSE;
return TRUE;
}
function objectShowPreview()
{
return TRUE;
}
function SendNotificationMail($sAction="add",$sMsg=null)
{
if(!$this->iAppId)
{
$oVersion = new version($this->iVersionId);
$sAppName = version::fullName($this->iVersionId);
$sMsg .= $oVersion->objectMakeUrl()."\n";
} else
{
$oApp = new application($this->iAppId);
$sAppName = $oApp->sName;
$sMsg .= $oApp->objectMakeUrl()."\n";
}
switch($sAction)
{
case "add":
$sSubject = "Note $this->sTitle for $sAppName added by ".
$_SESSION['current']->sRealname;
addmsg("The note was successfully added into the database.", "green");
break;
case "edit":
$sSubject = "Note $this->sTitle for $sAppName has been modified by ".
$_SESSION['current']->sRealname;
addmsg("Note modified.", "green");
break;
case "delete":
$oSubmitter = new User($this->iSubmitterId);
$sSubject = "Note $this->sTitle for $sAppName has been deleted by ".
$_SESSION['current']->sRealname;
$sMsg .= "This note was made on ".print_date(mysqldatetime_to_unixtimestamp($this->sSubmitTime)).
" by ".$oSubmitter->sRealname."\n";
$sMsg .= "\n";
$sMsg .= "Subject: ".$this->sTitle."\n";
$sMsg .= "\n";
$sMsg .= "Note contents:\n";
$sMsg .= $this->shDescription."\n";
$sMsg .= "\n";
$sMsg .= "Because:\n";
if(isset($aClean['sReplyText']) && $aClean['sReplyText'])
$sMsg .= $aClean['sReplyText']."\n";
else
$sMsg .= "No reason given.\n";
addmsg("Note deleted.", "green");
break;
}
$sEmail = User::get_notify_email_address_list(null, $this->iVersionId);
if($sEmail)
mail_appdb($sEmail, $sSubject ,$sMsg);
}
/* Show note */
/* $bDisplayOnly means we should not display any editing controls, even if */
/* the user has the ability to edit this note */
function display($aVars = null)
{
switch($this->sTitle)
{
case 'WARNING':
$sClass = 'warning';
$sTitle = 'Warning';
break;
case 'HOWTO':
$sClass = 'howto';
$sTitle = 'HOWTO';
break;
default:
if(!empty($this->sTitle))
$sTitle = $this->sTitle;
else
$sTitle = 'Note';
$sClass = 'defaultnote';
}
if(!$aVars || !getInput('shReturnTo', $aVars))
{
$oVersion = new version($this->iVersionId);
$shReturnTo = $oVersion->objectMakeUrl();
} else
{
$shReturnTo = $aVars['shReturnTo'];
}
$shOutput = html_frame_start("","98%",'',0);
$shOutput .= "<table width=\"100%\" border=\"0\" cellspacing=\"0\">\n";
$shOutput .= "<tr class=\"".$sClass."\" align=\"center\" valign=\"top\"><td>&nbsp;</td></tr><tr class=\"notetitle\" valign=\"top\" align=\"center\"><td>".$sTitle."</td></tr>\n";
$shOutput .= "<tr><td class=\"note\">\n";
$shOutput .= $this->shDescription;
$shOutput .= "</td></tr>\n";
if((!$aVars || $aVars['bEditing'] != "true") && $this->canEdit())
{
$shOutput .= "<tr class=\"color1\" align=\"center\" valign=\"top\"><td>";
$shOutput .= "<form method=\"post\" name=\"message\" action=\"objectManager.php?sClass=note&amp;sAction=edit&amp;iId=".$this->iNoteId."&amp;sReturnTo=".urlencode($shReturnTo)."\">";
$shOutput .= '<input type="submit" value="Edit note" class="button">';
$shOutput .= '</form></td></tr>';
}
$shOutput .= "</table>\n";
$shOutput .= html_frame_end();
echo $shOutput;
}
function displayNotesForEntry($iVersionId, $iAppId = null)
{
if($iVersionId)
{
$oVersion = new version($iVersionId);
$oApp = $oVersion->objectGetParent();
$hResult = query_parameters("SELECT noteId FROM appNotes WHERE versionId = '?' OR (appId = '?' AND (versionId = '?' OR versionId = '?')) ORDER BY versionId,noteId", $iVersionId, $oApp->objectGetId(), APPNOTE_SHOW_FOR_ALL, APPNOTE_SHOW_FOR_VERSIONS);
} else if($iAppId)
{
$hResult = query_parameters("SELECT noteId FROM appNotes WHERE appId = '?' AND (versionId = '?' OR versionId = '?')", $iAppId, APPNOTE_SHOW_FOR_ALL, APPNOTE_SHOW_FOR_APP);
}
if(!$hResult)
return;
if($iVersionId)
$oVersion = new version($iVersionId);
else
$oApp = new application($iAppId);
while($oRow = mysql_fetch_object($hResult))
{
$oNote = new note($oRow->noteId);
$shReturnTo = $iVersionId ? $oVersion->objectMakeUrl() : $oApp->objectMakeUrl();
$aVars = array('shReturnTo' => $shReturnTo, 'bEditing' => 'false');
$oLink = $oNote->getLink();
if($oLink)
$oLink->display($aVars);
else
$oNote->display($aVars);
}
}
function objectGetCustomVars($sAction)
{
switch($sAction)
{
case "preview":
return array("bEditing");
case "add":
return array('iVersionId','iAppId','sNoteTitle');
default:
return null;
}
}
public static function isRealVersionId($iVersionId)
{
return $iVersionId > 0;
}
public function hasRealVersionId()
{
return note::isRealVersionId($this->iVersionId);
}
public static function getDisplayModeIds()
{
return array(APPNOTE_SHOW_FOR_ALL, APPNOTE_SHOW_FOR_VERSIONS, APPNOTE_SHOW_FOR_APP, APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS);
}
public static function getDisplayModeNames()
{
return array('Show on both application and version pages', 'Show on all version pages only', 'Show on application page only', 'Show on the following version pages only:');
}
public function getDisplayModeName($iModeId = null)
{
if(!$iModeId)
$iModeId = $this->iVersionId;
$aNames = note::getDisplayModeNames();
$iIndex = 0;
foreach(note::getDisplayModeIds() as $iId)
{
if($iId == $iModeId)
return $aNames[$iIndex];
$iIndex++;
}
return '';
}
public function findLink($iVersionId, $bQueryDB = true)
{
if($bQueryDB)
{
// If we don't have a noteId we can't be linked to anything
if(!$this->iNoteId)
return null;
$hResult = query_parameters("SELECT * FROM appNotes WHERE linkedWith = '?' AND versionId = '?'", $this->iNoteId, $iVersionId);
if(!$hResult || !($oRow = mysql_fetch_object($hResult)))
return null;
return new noteLink(null, $oRow);
}
foreach($this->aNoteLinks as $oLink)
{
if($oLink->objectGetParent('version') == $iVersionId)
return $oLink;
}
return null;
}
public function isLinkedWith($iVersionId, $bQueryDB = true)
{
$oLink = $this->findLink($iVersionId, $bQueryDB);
return $oLink != null;
}
public function getNoteLinksFromInput($aValues)
{
$iAppId = $this->iAppId;
if(!$iAppId)
$iAppId = getInput('iAppId', $aValues);
$oApp = new application($iAppId);
$iCount = sizeof($oApp->getVersions());
$aLinkedVersions = html_read_input_series('iVersionId', $aValues, $iCount);
$aLinks = array();
foreach($aLinkedVersions as $sLinkedVersionId)
{
if(!$sLinkedVersionId)
continue;
$iLinkedVersionId = (int)$sLinkedVersionId;
// See if we already have a DB entry for this link
$oExistingLink = $this->findLink($iLinkedVersionId);
if($oExistingLink)
{
$aLinks[] = $oExistingLink;
continue;
}
$oLink = new noteLink();
$oLink->objectSetParent($this->iNoteId, 'note');
$oLink->objectSetParent($iLinkedVersionId, 'version');
$aLinks[] = $oLink;
}
return $aLinks;
}
public function saveNoteLinks($bNewNote = false)
{
foreach($this->aNoteLinks as $oLink)
{
if($bNewNote || !$this->isLinkedWith($oLink->objectGetParent('version')))
$oLink->create();
}
// Check if we should delete any links
$aDBLinks = $this->objectGetChildren();
if(sizeof($this->aNoteLinks) != sizeof($aDBLinks))
{
foreach($aDBLinks as $oDBLink)
{
$bFound = false;
foreach($this->aNoteLinks as $oLink)
{
if($oDBLink->objectGetParent('version') == $oLink->objectGetParent('version'))
$bFound = true;
}
if(!$bFound)
$oDBLink->delete();
}
}
}
public function getLink()
{
if($this->iLinkedWith)
return new noteLink($this->iNoteId);
return null;
}
function outputEditor($aValues = null)
{
if($aValues)
{
if(!$this->iVersionId)
$this->iVersionId = getInput('iVersionId', $aValues);
if(!$this->iAppId)
$this->iAppId = getInput('iAppId', $aValues);
if(!$this->sTitle)
$this->sTitle = getInput('sNoteTitle', $aValues);
}
if($this->iAppId && !$this->iVersionId)
$this->iVersionId = APPNOTE_SHOW_FOR_ALL;
if(!$this->iAppId)
{
$oVersion = new version($this->iVersionId);
$this->iAppId = $oVersion->iAppId;
}
HtmlAreaLoaderScript(array("editor"));
echo html_frame_start("Edit Application Note", "90%","",0);
echo html_table_begin("width='100%' border=0 align=left cellpadding=6 cellspacing=0 class='box-body'");
echo '<input type="hidden" name="bEditing" value="true">';
echo '<input type="hidden" name="iNoteId" value="'.$this->iNoteId.'">';
echo '<input type="hidden" name="iAppId" value="'.$this->iAppId.'">';
echo '<tr><td class=color1>Title</td>'."\n";
echo ' <td class=color0><input size=80% type="text" name="sNoteTitle" type="text" value="'.$this->sTitle.'"></td></tr>',"\n";
echo '<tr><td class=color4>Description</td><td class=color0>', "\n";
echo '<p style="width:700px">', "\n";
echo '<textarea cols="80" rows="20" id="editor" name="shNoteDesc">'.$this->shDescription.'</textarea>',"\n";
echo '</p>';
echo '</td></tr>'."\n";
if($this->iAppId || $oApp->canEdit())
{
if($this->hasRealVersionId())
{
$oLink = new noteLink();
$oLink->objectSetParent($this->iNoteId, 'note');
$oLink->objectSetParent($this->iVersionId, 'version');
$this->aNoteLinks[] = $oLink;
$oVersion = new version($this->iVersionId);
$this->iAppId = $oVersion->iAppId;
$this->iVersionId = APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS;
}
$oApp = new application($this->iAppId);
$aIds = $this->getDisplayModeIds();
$aOptions = $this->getDisplayModeNames();
echo '<tr><td class="color1">Display mode</td>'."\n";
echo '<td class="color0">'.html_radiobuttons($aIds, $aOptions, 'iVersionId', $this->iVersionId);
/* Allow the note to be shown for certain versions only */
$aIds = array();
$aOptions = array();
$aSelected = array();
foreach($oApp->getVersions(true) as $oAppVersion) // Only accepted versions
{
$aIds[] = $oAppVersion->objectGetId();
$aOptions[] = $oAppVersion->objectMakeLink();
$aSelected[] = $this->isLinkedWith($oAppVersion->objectGetId(), false);
}
echo html_checkboxes('iVersionId', $aIds, $aOptions, $aSelected);
echo '</td></tr>';
} else if(!$this->iAppId)
{
echo '<input type="hidden" name="iVersionId" value="'.$this->iVersionId.'">';
}
echo '<tr><td colspan="2" align="center" class="color3">',"\n";
echo html_table_end();
echo html_frame_end();
}
public function checkOutputEditorInput($aClean)
{
$shErrors = '';
$iVersionId = getInput('iVersionId', $aClean);
if($iVersionId == APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS)
{
$aNoteLinks = $this->getNoteLinksFromInput($aClean);
if(!sizeof($aNoteLinks))
$shErrors .= '<li>You need to show the note for at least one version, or choose another display mode</li>';
}
return $shErrors;
}
/* retrieves values from $aValue that were output by outputEditor() */
/* $aValues can be $_REQUEST or any array with the values from outputEditor() */
function GetOutputEditorValues($aValues)
{
$this->iVersionId = getInput('iVersionId', $aValues);
if(!$this->isRealVersionId($this->iVersionId))
$this->iAppId = getInput('iAppId', $aValues);
else
$this->iAppId = 0;
if($this->iVersionId == APPNOTE_SHOW_FOR_SPECIFIC_VERSIONS)
{
$this->aNoteLinks = $this->getNoteLinksFromInput($aValues);
// There's no need to use links if the note is only shown for one version
if(sizeof($this->aNoteLinks) == 1)
{
$oLink = $this->aNoteLinks[0];
$this->iVersionId = $oLink->objectGetParent('version');
$this->iAppId = 0;
$this->aNoteLinks = array();
}
}
$this->sTitle = $aValues['sNoteTitle'];
$this->shDescription = $aValues['shNoteDesc'];
}
function allowAnonymousSubmissions()
{
return false;
}
// NOTE: notes cannot be queued at this point
function mustBeQueued()
{
return false;
}
function objectGetId()
{
return $this->iNoteId;
}
// TODO: we ignore $bQueued and $bRejected as notes
// do not support queuing at this point
// TODO: we have no permissions scope on retrieving entries
// as notes are typically only added to unqueued versions
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true)
{
$sQuery = "select * from appNotes";
$hResult = query_parameters($sQuery);
return $hResult;
}
function objectGetEntriesCount($sState)
{
$sQuery = "SELECT COUNT(DISTINCT noteId) as count FROM appNotes";
$hResult = query_parameters($sQuery);
if(!$hResult)
return false;
if(($oRow = mysql_fetch_object($hResult)))
return $oRow->count;
return false;
}
//TODO: not sure how to best let users view a table of notes
// since the note contents could be very long we would only
// want to show a small amount of the text. Implement this
// routine when we need it
function objectGetHeader()
{
return null;
}
//TODO: implement this when we implement objectGetHeader()
function objectGetTableRow()
{
return null;
}
function objectMakeUrl()
{
$oManager = new objectManager("note", "View Note");
return $oManager->makeUrl("view", $this->objectGetId());
}
function objectGetSubmitterId()
{
return $this->iSubmitterId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
/* We don't do this at the moment */
return array(null, null, null);
}
public function objectGetParent($sClass = '')
{
if($this->hasRealVersionId())
return new version($this->iVersionId);
else
return new application($this->iAppId);
}
public function objectSetParent($iNewId, $sClass = '')
{
if($this->hasRealVersionId())
$this->iVersionId = $iNewId;
else
$this->iAppId = $iNewId;
}
function objectGetChildren($bIncludeDeleted = false)
{
$aRet = array();
if(!$this->iAppId)
return $aRet;
$hResult = query_parameters("SELECT * FROM appNotes WHERE linkedWith = '?'", $this->iNoteId);
if(!$hResult)
return $aRet;
while($oRow = mysql_fetch_object($hResult))
$aRet[] = new noteLink(null, $oRow);
return $aRet;
}
//TODO: not sure if we want to use sTitle here or what
function objectMakeLink()
{
$sLink = "<a href=\"".$this->objectMakeUrl()."\">".
$this->sTitle."</a>";
return $sLink;
}
function objectGetState()
{
return 'accepted'; // We don't queue notes
}
// users can edit the note if they:
// - have "admin" privileges
// - maintain the version, or supermaintain the application that
// this version is under
function canEdit()
{
if($_SESSION['current']->hasPriv("admin"))
return true;
else if($this->iVersionId && !$this->iAppId)
return maintainer::isUserMaintainer($_SESSION['current'], $this->iVersionId);
else if($this->iAppId)
return maintainer::isUserSuperMaintainer($_SESSION['current'], $this->iAppId);
return false;
}
}
class noteLink
{
private $iLinkId;
private $iNoteId;
private $iVersionId;
function noteLink($iLinkId = null, $oRow = null)
{
$this->iLinkId = $iLinkId;
if(!$oRow && $this->iLinkId)
{
$hResult = query_parameters("SELECT * FROM appNotes WHERE noteId = '?'", $this->iLinkId);
if(!$hResult)
return;
$oRow = mysql_fetch_object($hResult);
}
if($oRow)
{
$this->iLinkId = $oRow->noteId;
$this->iNoteId = $oRow->linkedWith;
$this->iVersionId = $oRow->versionId;
}
}
public function create()
{
$hResult = query_parameters("INSERT INTO appNotes (linkedWith,versionId) VALUES('?','?')", $this->iNoteId, $this->iVersionId);
if(!$hResult)
return false;
return true;
}
public function isDuplicate()
{
$oNote = new note($this->iNoteId);
return $oNote->isLinkedWith($this->iVersionId);
}
public function update()
{
// Query the DB so we have something to compare against
$oLink = new noteLink($this->iLinkId);
if($this->objectGetParent('version') != $oLink->objectGetParent('version') && !$this->isDuplicate())
{
$hResult = query_parameters("UPDATE appNotes SET versionId = '?' WHERE noteId = '?'", $this->iVersionId, $this->iNoteId);
if(!$hResult)
return false;
}
return true;
}
public function delete()
{
$hResult = query_parameters("DELETE FROM appNotes WHERE noteId = '?'", $this->iLinkId);
if(!$hResult)
return false;
return true;
}
public function objectSetParent($iNewId, $sClass = '')
{
if(!$sClass || $sClass == 'note')
$this->iNoteId = $iNewId;
else if($sClass == 'version')
$this->iVersionId = $iNewId;
}
public function objectGetParent($sClass = '')
{
if(!$sClass || $sClass == 'note')
return $this->iNoteId;
if($sClass == 'version')
return $this->iVersionId;
}
function display($aValues = null)
{
$oNote = new note($this->iNoteId);
$oNote->display($aValues);
}
}
?>

1934
include/objectManager.php Normal file

File diff suppressed because it is too large Load Diff

84
include/parsedate.php Normal file
View File

@@ -0,0 +1,84 @@
<?php
function parsedate($datestr)
{
$daynames = array("monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday");
$monthnames = array("jan" => 1, "feb" => 2, "mar" => 3, "apr" => 4, "may" => 5, "jun" => 6,
"jul" => 7, "aug" => 8, "sep" => 9, "oct" => 10, "nov" => 11, "dec" => 12);
$ampm = array("am" => 00, "pm" => 12);
if(!$datestr)
return -1;
$datestr = strtolower($datestr);
$datestr = ereg_replace("[,]", "", $datestr);
$dp = explode(' ', $datestr);
while(list($idx, $part) = each($dp))
{
//echo "PART($part)<br>";
/* 23:59:59 */
if(ereg("^([0-9]+):([0-9]+):([0-9]+)$", $part, $arr))
{
$hour = $arr[1];
$minute = $arr[2];
$second = $arr[3];
continue;
}
/* 23:59 */
if(ereg("^([0-9]+):([0-9]+)$", $part, $arr))
{
$hour = $arr[1];
$minute = $arr[2];
$second = 0;
continue;
}
/* 2000-12-31 (mysql date format) */
if(ereg("^([0-9][0-9][0-9][0-9])-([0-9][0-9])-([0-9][0-9])$", $part, $arr))
{
$year = $arr[1];
$month = $arr[2];
$day = $arr[3];
continue;
}
if(defined($ampm[$part]))
{
$hour += $ampm[$part];
continue;
}
if($monthnames[substr($part, 0, 3)])
{
$month = $monthnames[substr($part, 0, 3)];
continue;
}
if($part > 1900)
{
$year = $part;
continue;
}
if($part > 31)
{
$year = 1900 + $part;
continue;
}
if($part >= 1 && $part <= 31)
{
$day = $part;
continue;
}
//echo "Unparsed: '$part'<br>\n";
}
return mktime($hour, $minute, $second, $month, $day, $year);
}
?>

232
include/query.php Normal file
View File

@@ -0,0 +1,232 @@
<?php
$hAppdbLink = null;
$hBugzillaLink = null;
define("MYSQL_DEADLOCK_ERRNO", 1213);
function query_appdb($sQuery, $sComment="")
{
global $hAppdbLink;
if(!is_resource($hAppdbLink))
{
// The last argument makes sure we are really opening a new connection
$hAppdbLink = mysql_connect(APPS_DBHOST, APPS_DBUSER, APPS_DBPASS, true);
if(!$hAppdbLink)
die("Database error, please try again soon.");
mysql_select_db(APPS_DB, $hAppdbLink);
}
$iRetries = 2;
/* we need to retry queries that hit transaction deadlocks */
/* as a deadlock isn't really a failure */
while($iRetries)
{
$hResult = mysql_query($sQuery, $hAppdbLink);
if(!$hResult)
{
/* if this error isn't a deadlock OR if it is a deadlock and we've */
/* run out of retries, report the error */
$iErrno = mysql_errno($hAppdbLink);
if(($iErrno != MYSQL_DEADLOCK_ERRNO) || (($iErrno == MYSQL_DEADLOCK_ERRNO) && ($iRetries <= 0)))
{
query_error($sQuery, $sComment, $hAppdbLink);
return $hResult;
}
$iRetries--;
} else
{
return $hResult;
}
}
return NULL;
}
/*
* Wildcard Rules
* SCALAR (?) => 'original string quoted'
* OPAQUE (&) => 'string from file quoted'
* MISC (~) => original string (left 'as-is')
*
* NOTE: These rules convienently match those for Pear DB
*
* MySQL Prepare Function
* By: Kage (Alex)
* KageKonjou@GMail.com
* http://us3.php.net/manual/en/function.mysql-query.php#53400
*
* Modified by CMM 20060622
*
* Values are mysql_real_escape_string()'d to prevent against injection attacks
* See http://php.net/mysql_real_escape_string for more information about why this is the case
*
* Usage:
* $hResult = query_parameters("Select * from mytable where userid = '?'",
* $iUserId);
*
* Note:
* Ensure that all variables are passed as parameters to query_parameters()
* to ensure that sql injection attacks are prevented against
*
*/
function query_parameters()
{
global $hAppdbLink;
if(!is_resource($hAppdbLink))
{
// The last argument makes sure we are really opening a new connection
$hAppdbLink = mysql_connect(APPS_DBHOST, APPS_DBUSER, APPS_DBPASS, true) or die('Database error, please try again soon: '.mysql_error());
mysql_select_db(APPS_DB, $hAppdbLink);
}
$aData = func_get_args();
$sQuery = $aData[0];
$aTokens = split("[&?~]", $sQuery); /* NOTE: no need to escape characters inside of [] in regex */
$sPreparedquery = $aTokens[0];
$iCount = strlen($aTokens[0]);
/* do we have the correct number of tokens to the number of parameters provided? */
if(count($aTokens) != count($aData))
return NULL; /* count mismatch, return NULL */
for ($i=1; $i < count($aTokens); $i++)
{
$char = substr($sQuery, $iCount, 1);
$iCount += (strlen($aTokens[$i])+1);
if ($char == "&")
{
$fp = @fopen($aData[$i], 'r');
$pdata = "";
if ($fp)
{
while (($sBuf = fread($fp, 4096)) != false)
{
$pdata .= $sBuf;
}
fclose($fp);
}
} else
{
$pdata = &$aData[$i];
}
$sPreparedquery .= ($char != "~" ? mysql_real_escape_string($pdata) : $pdata);
$sPreparedquery .= $aTokens[$i];
}
return query_appdb($sPreparedquery);
}
function query_bugzilladb($sQuery,$sComment="")
{
global $hBugzillaLink;
if(!is_resource($hBugzillaLink))
{
// The last argument makes sure we are really opening a new connection
$hBugzillaLink = mysql_connect(BUGZILLA_DBHOST, BUGZILLA_DBUSER, BUGZILLA_DBPASS, true);
if(!$hBugzillaLink) return;
mysql_select_db(BUGZILLA_DB, $hBugzillaLink);
}
$hResult = mysql_query($sQuery, $hBugzillaLink);
if(!$hResult) query_error($sQuery, $sComment, $hBugzillaLink);
return $hResult;
}
function query_error($sQuery, $sComment, $hLink)
{
static $bInQueryError = false;
// if we are already reporting an error we can't report it again
// as that indicates that error reporting itself produced an error
if($bInQueryError)
return;
// record that we are inside of this function, we don't want to recurse
$bInQueryError = true;
error_log::log_error(ERROR_SQL, "Query: '".$sQuery."' ".
"mysql_errno(): '".mysql_errno($hLink)."' ".
"mysql_error(): '".mysql_error($hLink)."' ".
"comment: '".$sComment."'");
$sStatusMessage = "<p><b>An internal error has occurred and has been logged and reported to appdb admins</b></p>";
addmsg($sStatusMessage);
$bInQueryError = false; // clear variable upon exit
}
function query_fetch_row($hResult)
{
return mysql_fetch_row($hResult);
}
function query_fetch_object($hResult)
{
return mysql_fetch_object($hResult);
}
function query_appdb_insert_id()
{
global $hAppdbLink;
return mysql_insert_id($hAppdbLink);
}
function query_bugzilla_insert_id()
{
global $hBugzillaLink;
return mysql_insert_id($hBugzillaLink);
}
function query_num_rows($hResult)
{
return mysql_num_rows($hResult);
}
function query_escape_string($sString)
{
global $hAppdbLink;
if(!is_resource($hAppdbLink))
{
// The last argument makes sure we are really opening a new connection
$hAppdbLink = mysql_connect(APPS_DBHOST, APPS_DBUSER, APPS_DBPASS, true);
if(!$hAppdbLink)
die("Database error, please try again soon.");
mysql_select_db(APPS_DB, $hAppdbLink);
}
return mysql_real_escape_string($sString, $hAppdbLink);
}
function query_field_type($hResult, $iFieldOffset)
{
return mysql_field_type($hResult, $iFieldOffset);
}
function query_field_name($hResult, $iFieldOffset)
{
return mysql_field_name($hResult, $iFieldOffset);
}
function query_field_len($hResult, $ifieldOffset)
{
return mysql_field_len($hResult, $iFieldOffset);
}
function query_field_flags($hResult, $iFieldOffset)
{
return mysql_field_flags($hResult, $iFieldOffset);
}
function query_fetch_field($hResult, $iFieldOffset)
{
return mysql_fetch_field($hResult, $iFieldOffset);
}
?>

832
include/screenshot.php Normal file
View File

@@ -0,0 +1,832 @@
<?php
/******************************************/
/* screenshot class and related functions */
/******************************************/
require_once(BASE."include/util.php");
require_once(BASE."include/image.php");
// load the watermark
$watermark = new Image("/images/watermark.png");
/**
* Screenshot class for handling screenshots and thumbnails
*/
class screenshot
{
var $iScreenshotId;
// parameters necessary for creating a new screenshot with
// Screenshot::create()
var $iVersionId;
var $hFile;
var $sDescription;
var $oScreenshotImage;
var $oThumbnailImage;
var $bQueued;
var $iAppId;
var $sUrl;
var $sSubmitTime;
var $iSubmitterId;
/**
* Constructor, fetches the data and image objects if $iScreenshotId is given.
*/
function Screenshot($iScreenshotId = null, $oRow = null)
{
// we are working on an existing screenshot
if(!$iScreenshotId && !$oRow)
return;
if(!$oRow)
{
$hResult = query_parameters("SELECT appData.*, appVersion.appId AS appId
FROM appData, appVersion
WHERE appData.versionId = appVersion.versionId
AND id = '?'
AND type = 'screenshot'", $iScreenshotId);
if($hResult)
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iScreenshotId = $oRow->id;
$this->sDescription = $oRow->description;
$this->iAppId = $oRow->appId;
$this->iVersionId = $oRow->versionId;
$this->sUrl = $oRow->url;
$this->bQueued = ($oRow->state=='queued')?true:false;
$this->sSubmitTime = $oRow->submitTime;
$this->iSubmitterId = $oRow->submitterId;
$this->hFile = null;
}
}
/**
* Creates a new screenshot.
*/
function create()
{
$hResult = query_parameters("INSERT INTO appData
(versionId, type, description, state, submitTime, submitterId)
VALUES('?', '?', '?', '?', ?, '?')",
$this->iVersionId, "screenshot",
$this->sDescription,
$this->mustBeQueued() ? 'queued' : 'accepted',
"NOW()",
$_SESSION['current']->iUserId);
if($hResult)
{
$this->iScreenshotId = query_appdb_insert_id();
/* make sure we supply the full path to move_uploaded_file() */
$moveToPath = appdb_fullpath("data/screenshots/originals/").$this->iScreenshotId;
if(!move_uploaded_file($this->hFile['tmp_name'], $moveToPath))
{
// whoops, moving failed, do something
addmsg("Unable to move screenshot from '".$this->hFile['tmp_name']."' to '".$moveToPath."'", "red");
$sQuery = "DELETE
FROM appData
WHERE id = '?'";
query_parameters($sQuery, $this->iScreenshotId);
return false;
} else // we managed to copy the file, now we have to process the image
{
$this->sUrl = $this->iScreenshotId;
if($this->generate())
{
// we have to update the entry now that we know its name
$sQuery = "UPDATE appData
SET url = '?'
WHERE id = '?'";
if (!query_parameters($sQuery, $this->iScreenshotId, $this->iScreenshotId)) return false;
} else
{
addmsg("Unable to generate image or thumbnail. The file format might not be recognized. Please use PNG or JPEG only.","red");
$sQuery = "DELETE
FROM appData
WHERE id = '?'";
query_parameters($sQuery, $this->iScreenshotId);
return false;
}
}
$this->screenshot($this->iScreenshotId,$this->bQueued);
$this->mailMaintainers();
return true;
}
else
{
addmsg("Error while creating a new screenshot.", "red");
return false;
}
}
function purge()
{
return $this->delete();
}
/**
* Deletes the screenshot from the database.
* and request its deletion from the filesystem (including the thumbnail).
*
* Returns: true if deletion was success, false if otherwise
*/
function delete()
{
/* appData has a universal function for removing database entries */
$oAppData = new appData($this->iScreenshotId, null, $this);
if($oAppData->delete())
{
/* make sure the screenshot and thumbnail is loaded */
/* up before we try to delete them */
$this->load_image(true);
$this->load_image(false);
$this->oScreenshotImage->delete();
$this->oThumbnailImage->delete();
// if the original file exists, delete it
$sOriginalFilename = appdb_fullpath("/data/screenshots/originals/".$this->iScreenshotId);
if(is_file($sOriginalFilename))
unlink($sOriginalFilename);
}
return true;
}
function reject()
{
$this->delete();
}
/**
* Move screenshot out of the queue.
*/
function unQueue()
{
// If we are not in the queue, we can't move the screenshot out of the queue.
if(!$this->bQueued)
return false;
if(query_parameters("UPDATE appData SET state = '?' WHERE id='?'",
'accepted', $this->iScreenshotId))
{
$this->bQueued = false;
// we send an e-mail to interested people
$this->mailSubmitter();
$this->mailMaintainers();
// the screenshot has been unqueued
addmsg("The screenshot has been unqueued.", "green");
}
}
/**
* Cleans up the memory.
*/
function free()
{
if($this->oScreenshotImage)
$this->oScreenshotImage->destroy();
if($this->oThumbnailImage)
$this->oThumbnailImage->destroy();
}
/**
* Sets the screenshot description.
*/
function setDescription($sDescription)
{
if($hResult = query_parameters("UPDATE id SET description = '?' WHERE id = '?' AND type = 'screenshot'",
$sDescription, $this->iScreenshotId))
$this->sDescription = $sDescription;
}
/**
* This method generates a watermarked screenshot and thumbnail from the original file.
* Useful when changing thumbnail, upgrading GD, adding an image, etc.
* Return false if an image could not be loaded.
*/
function generate()
{
global $watermark;
// first we will create the thumbnail
// load the screenshot
$this->oThumbnailImage = new Image("/data/screenshots/originals/".$this->sUrl);
if(!$this->oThumbnailImage->isLoaded())
{
$this->oThumbnailImage->delete(); // if we cannot load the original file we delete it from the filesystem
return false;
}
$this->oThumbnailImage->make_thumb(0,0,1,'#000000');
// store the image
$this->oThumbnailImage->output_to_file(appdb_fullpath("/data/screenshots/thumbnails/".$this->sUrl));
// now we'll process the screenshot image for watermarking
// load the screenshot
$this->oScreenshotImage = new Image("/data/screenshots/originals/".$this->sUrl);
if(!$this->oScreenshotImage->isLoaded()) return false;
// resize the image
$this->oScreenshotImage->make_full();
// store the resized image
$this->oScreenshotImage->output_to_file(appdb_fullpath("/data/screenshots/".$this->sUrl));
// reload the resized screenshot
$this->oScreenshotImage = new Image("/data/screenshots/".$this->sUrl);
if(!$this->oScreenshotImage->isLoaded()) return false;
// add the watermark to the screenshot
$this->oScreenshotImage->add_watermark($watermark->get_image_resource());
// store the watermarked image
$this->oScreenshotImage->output_to_file(appdb_fullpath("/data/screenshots/".$this->sUrl));
return true;
}
/* ensure that either the thumbnail or screenshot */
/* has been loaded into memory */
function load_image($bThumbnail)
{
if($bThumbnail)
{
/* if we haven't loaded the thumbnail up yet, do so */
if(!$this->oThumbnailImage)
$this->oThumbnailImage = new Image("/data/screenshots/thumbnails/".$this->sUrl);
} else
{
/* if we haven't loaded the screenshot up yet, do so */
if(!$this->oScreenshotImage)
$this->oScreenshotImage = new Image("/data/screenshots/".$this->sUrl);
}
}
/* output the thumbnail if $bThumbnail or the full screenshot if !$bThumbnail */
/* NOTE: use this instead of calling through to this classes oScreenshot or */
/* oThumbnail objects directly to their output_*() functions */
function output_screenshot($bThumbnail)
{
$this->load_image($bThumbnail);
if($bThumbnail)
{
if($this->oThumbnailImage)
$this->oThumbnailImage->output_to_browser(1);
} else
{
if($this->oScreenshotImage)
$this->oScreenshotImage->output_to_browser(1);
}
}
/* Accessor functions for the screenshot and thumbnail images that this */
/* screenshot object encapsulates */
/* NOTE: DO NOT call like $oScreenshot->oScreenshotImage->get_width(), there is NO */
/* guarantee that oScreenshotImage will be valid */
function get_screenshot_width()
{
$this->load_image(false);
return $this->oScreenshotImage->get_width();
}
public function objectGetParent($sClass = '')
{
$oAppData = new appData($this->iScreenshotId, null, $this);
return $oAppData->objectGetParent();
}
public function objectSetParent($iNewId, $sClass = '')
{
if($this->iVersionId)
$this->iVersionId = $iNewId;
else
$this->iAppId = $iNewId;
}
function objectGetChildren($bIncludeDeleted = false)
{
/* We have none */
return array();
}
function get_screenshot_height()
{
$this->load_image(false);
return $this->oScreenshotImage->get_height();
}
function get_thumbnail_width()
{
$this->load_image(true);
return $this->oThumbnailImage->get_width();
}
function get_thumbnail_height()
{
$this->load_image(true);
return $this->oThumbnailImage->get_height();
}
function objectGetSubmitterId()
{
return $this->iSubmitterId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
$oOptions = new mailOptions();
if($sAction == "delete" && $bParentAction)
$oOptions->bMailOnce = TRUE;
return $oOptions;
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
$sFor = version::fullName($this->iVersionId);
$sMsg = null;
$sSubject = null;
if($bMailSubmitter)
{
switch($sAction)
{
case "delete":
if($bParentAction)
{
$sSubject = "Submitter screenshots deleted";
$sMsg = "The screenshots you submitted for $sFor have been ".
"deleted because $sFor was deleted.";
} else
{
$sSubject = "Submitted screenshot deleted";
$sMsg = "The screenshot with description '".$this->sDescription.
"' that you submitted for $sFor has been deleted.";
}
break;
}
$aMailTo = null;
} else
{
switch($sAction)
{
case "delete":
if(!$bParentAction)
{
$sSubject = "Screenshot for $sFor deleted";
$sMsg = "The screenshot with description '".$this->sDescription.
"' for $sFor has been deleted.";
}
break;
}
$aMailTo = User::get_notify_email_address_list(null, $this->iVersionId);
}
return array($sSubject, $sMsg, $aMailTo);
}
function mailSubmitter($bRejected=false)
{
global $aClean;
if($this->iSubmitterId)
{
$sAppName = Application::lookup_name($this->iAppId)." ".Version::lookup_name($this->iVersionId);
$oSubmitter = new User($this->iSubmitterId);
if(!$bRejected)
{
$sSubject = "Submitted screenshot accepted";
$sMsg = "The screenshot you submitted for ".$sAppName." has been accepted.";
} else
{
$sSubject = "Submitted screenshot rejected";
$sMsg = "The screenshot you submitted for ".$sAppName." has been rejected.";
}
$sMsg .= $aClean['sReplyText']."\n";
$sMsg .= "We appreciate your help in making the Application Database better for all users.";
mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg);
}
}
function mailMaintainers($bDeleted=false)
{
$oVersion = new version($this->iVersionId);
$sAppName = version::fullName($this->iVersionId);
if(!$bDeleted)
$sMsg = $this->objectMakeUrl()."\n";
else
$sMsg = $oVersion->objectMakeUrl()."\n";
if(!$bDeleted)
{
if(!$this->bQueued)
{
$sSubject = "Screenshot for $sAppName added by ".
$_SESSION['current']->sRealname;
if($this->iSubmitterId)
{
$oSubmitter = new User($this->iSubmitterId);
$sMsg .= "This screenshot has been submitted by ".
$oSubmitter->sRealname.".";
$sMsg .= "\n";
}
addmsg("The screenshot was successfully added into the database.",
"green");
} else // Screenshot queued.
{
$sSubject = "Screenshot for $sAppName submitted by ".
$_SESSION['current']->sRealname;
$sMsg .= "This screenshot has been queued.";
$sMsg .= "\n";
addmsg("The screenshot you submitted will be added to the ".
"database after being reviewed.", "green");
}
} else // Screenshot deleted.
{
$sSubject = "Screenshot for $sAppName deleted by ".
$_SESSION['current']->sRealname;
addmsg("Screenshot deleted.", "green");
}
$sEmail = User::get_notify_email_address_list(null, $this->iVersionId);
if($sEmail)
mail_appdb($sEmail, $sSubject ,$sMsg);
}
function get_zoomicon_overlay()
{
/* if the user is using mozilla or firefox show the zoom icon over images */
/* otherwise because IE doesn't support transparent PNGs or proper css we have to */
/* skip it for IE */
if(strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") === false)
{
$sZoomIcon = '<img class="zoom_overlay" src="'.BASE.'images/xmag_32.png" alt="">';
}
else
$sZoomIcon = "";
return $sZoomIcon;
}
/**
* Get a random image for a particular version of an app.
* If the version is not set, get a random app image
*
* $bFormatting == false turns off all extranious formatting applied to the returned image html
*/
function get_random_screenshot_img($iAppId = null, $iVersionId = null,
$bFormatting = true)
{
// initialize variables to avoid notices when appending to them
$hResult = null;
$sImgFile = '';
$sImg = '';
// we want a random screenshots for this app
if($iAppId && !$iVersionId)
{
$hResult = query_parameters("SELECT appData.id, appData.description, RAND() AS rand
FROM appData, appVersion
WHERE appData.versionId = appVersion.versionId
AND appVersion.appId = '?'
AND type = 'screenshot'
AND appData.state = 'accepted'
ORDER BY rand", $iAppId);
} else if ($iVersionId) // we want a random screenshot for this version
{
$hResult = query_parameters("SELECT id, description, RAND() AS rand
FROM appData
WHERE versionId = '?'
AND type = 'screenshot'
AND state = 'accepted'
ORDER BY rand", $iVersionId);
}
if($bFormatting)
$sImgFile .= '<center>';
if(!$hResult || !query_num_rows($hResult))
{
$sImgFile.= '<img src="images/no_screenshot.png" alt="No Screenshot">';
} else
{
$oRow = query_fetch_object($hResult);
$sImgFile.= '<img src="appimage.php?bThumbnail=true&amp;iId='.$oRow->id.'" alt="'.$oRow->description.'">';
}
if($bFormatting)
$sImgFile .= '</center>';
if($bFormatting)
$sImg = html_frame_start("",'128','',2);
/* retrieve the url for the zoom icon overlay */
$sZoomIcon = Screenshot::get_zoomicon_overlay();
/* we have screenshots */
if($hResult && query_num_rows($hResult))
{
if($iVersionId)
$sImg .= "<div class=\"imgarea\"><a href='screenshots.php?iAppId=$iAppId&amp;iVersionId=$iVersionId'>".$sImgFile.$sZoomIcon."<br>View/Submit&nbsp;Screenshot</a></div>";
else
$sImg .= "<div class=\"imgarea\"><a href='screenshots.php?iAppId=$iAppId&amp;iVersionId=$iVersionId'>".$sImgFile.$sZoomIcon."<br>View&nbsp;Screenshot</a></div>";
} else if($iVersionId) /* we are asking for a specific app version but it has no screenshots */
{
$sImg .= "<div class=\"imgarea\"><a href='screenshots.php?iAppId=$iAppId&amp;iVersionId=$iVersionId'>".$sImgFile.$sZoomIcon."<br>Submit&nbsp;Screenshot</a></div>";
} else /* we have no screenshots and we aren't a specific version, we don't allow adding screenshots for an app */
{
$sImg .= $sImgFile.$sZoomIcon;
}
if($bFormatting)
$sImg .= html_frame_end()."<br>";
return $sImg;
}
function get_screenshots($iAppId = null, $iVersionId = null, $bQueued = "false")
{
/*
* We want all screenshots for this app.
*/
if($iAppId && !$iVersionId)
{
$hResult = query_parameters("SELECT appData.*, appVersion.appId as appId
FROM appData, appVersion
WHERE appVersion.versionId = appData.versionId
AND type = 'screenshot'
AND appVersion.appId = '?'
AND appData.state = '?'", $iAppId, ($bQueued == 'false') ? 'accepted' : 'queued');
}
/*
* We want all screenshots for this version.
*/
else if ($iVersionId)
{
$hResult = query_parameters("SELECT appData.*, appVersion.appId as appId
FROM appData, appVersion
WHERE appVersion.versionId = appData.versionId
AND type = 'screenshot'
AND appData.versionId = '?'
AND appData.state = '?'", $iVersionId, ($bQueued == 'false') ? 'accepted' : 'queued');
} else
{
return false;
}
return $hResult;
}
function get_thumbnail_img()
{
// generate random tag for popup window
$sRandName = User::generate_passwd(5);
// set img tag
$shImgSRC = '<img src="'.apidb_fullurl("appimage.php").
'?bThumbnail=true&amp;iId='.$this->iScreenshotId.'" alt="'.$this->sDescription.
'" width="'.$this->get_thumbnail_width().
'" height="'.$this->get_thumbnail_height().'">';
$shImg = '<a href="'.apidb_fullurl("appimage.php").
'?iId='.$this->iScreenshotId.
'" onclick="javascript:openWin(\''.apidb_fullurl("appimage.php").
'?iId='.$this->iScreenshotId.'\',\''.$sRandName.'\','.
($this->get_screenshot_width() + 20).','.
($this->get_screenshot_height() + 6).
');return false;">'.$shImgSRC.Screenshot::get_zoomicon_overlay().'</a>';
// set image link based on user pref
if ($_SESSION['current']->isLoggedIn())
{
if ($_SESSION['current']->getpref("window:screenshot") == "no")
{
$shImg = '<a href="'.apidb_fullurl("appimage.php").
'?iImageId='.$this->iScreenshotId.'">'.$shImgSRC.'</a>';
}
}
return $shImg;
}
public static function objectGetItemsPerPage($sState = 'accepted')
{
if($sState != 'accepted')
{
$aItemsPerPage = array(25, 50, 100, 200);
$iDefaultPerPage = 25;
} else
{
$aItemsPerPage = array(6, 9, 12, 15, 18, 21, 24);
$iDefaultPerPage = 6;
}
return array($aItemsPerPage, $iDefaultPerPage);
}
function objectWantCustomDraw($sWhat, $sQueued)
{
switch($sWhat)
{
case 'table':
if($sQueued == 'false')
return true;
break;
}
return false;
}
function objectDrawCustomTable($hResult, $sQueued)
{
echo "<div align=center><table><tr>\n";
for($i = 1; $oRow = query_fetch_object($hResult); $i++)
{
// display thumbnail
$oVersion = new version($oRow->versionId);
$oApp = new Application($oVersion->iAppId);
$oScreenshot = new Screenshot($oRow->id);
$shImg = $oScreenshot->get_thumbnail_img();
echo "<td align=center>\n";
echo $shImg;
echo "<div align=center>". substr($oRow->description,0,20). "\n";
echo "<br>[".$oApp->objectMakeLink()."]";
echo "<br>[".$oVersion->objectMakeLink()."]";
if($oScreenshot->canEdit())
{
$oM = new objectManager('screenshot');
echo '<br />[<a href="'.$oM->makeUrl('delete', $oScreenshot->objectGetId(), 'Delete Screenshot').'">Delete</a>]';
}
echo "</div></td>\n";
// end row if counter of 3
if($i % 3 == 0)
echo "</tr><tr>\n";
}
echo "</tr></table></div><br>\n";
}
public function objectGetFilterInfo()
{
$oFilter = new filterInterface();
$aCatNames = array();
$aCatIds = array();
$aCategories = category::getOrderedList();
foreach($aCategories as $oCategory)
{
$aCatNames[] = $oCategory->sName;
$aCatIds[] = $oCategory->objectGetId();
}
$oFilter->addFilterInfo('appCategory', 'App category', array(FILTER_OPTION_ENUM), FILTER_VALUES_OPTION_ENUM, $aCatIds, $aCatNames);
return $oFilter;
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = '', $bAscending = true, $oFilters = null)
{
return appData::objectGetEntries($sState, $iRows, $iStart, $sOrderBy, $bAscending,
'screenshot', $oFilters);
}
function objectGetEntriesCount($sState, $oFilters = null)
{
return appData::objectGetEntriesCount($sState, 'screenshot', $oFilters);
}
function objectGetHeader()
{
return appData::objectGetHeader("screenshot");
}
function objectGetState()
{
return ($this->bQueued) ? 'queued' : 'accepted';
}
function canEdit()
{
if($this)
{
$oAppData = new appData($this->objectGetId(), null, $this);
return $oAppData->canEdit();
} else
return appData::canEdit();
}
function mustBeQueued()
{
if($this)
{
$oAppData = new appData();
$oAppData->iVersionId = $this->iVersionId;
$oAppData->iAppId = NULL;
return $oAppData->mustBeQueued();
} else
return appData::mustBeQueued();
}
function objectGetTableRow()
{
$oAppData = new AppData($this->iScreenshotId, null, $this);
return $oAppData->objectGetTableRow();
}
function objectDisplayQueueProcessingHelp()
{
$shRet = "<p>This is the list of screenshots waiting to be processed</p>";
$shRet .= "<p>To view and process an entry, use the links under &#8216;Action&#8217;</p>";
return $shRet;
}
function outputEditor()
{
$oAppData = new appData($this->iScreenshotId, null, $this);
$oAppData->outputEditorGeneric();
echo '<tr valign=top><td class=color0><b>Submitted screenshot</b></td>',"\n";
echo '<td>';
$imgSRC = '<img width="'.$this->get_thumbnail_width().'" height="'.
$this->get_thumbnail_height().'" src="'.BASE.
'appimage.php?bQueued=true&amp;iId='.$this->iScreenshotId.'" />';
// generate random tag for popup window
$randName = User::generate_passwd(5);
// set image link based on user pref
$img = '<a href="javascript:openWin(\''.BASE.'appimage.php?bQueued=true&amp;iId='.
$this->iScreenshotId.'\',\''.$randName.'\','.$this->get_screenshot_width()
.','.($this->get_screenshot_height()+4).');">'.$imgSRC.'</a>';
if ($_SESSION['current']->isLoggedIn())
{
if ($_SESSION['current']->getpref("window:screenshot") == "no")
{
$img = '<a href="'.BASE.'appimage.php?bQueued=true&amp;iId='.
$this->iScreenshotId.'">'.$imgSRC.'</a>';
}
}
echo $img;
echo '</td></tr>',"\n";
echo '<input type="hidden" name="iScreenshotId" value="'.
$this->iScreenshotId.'" />';
echo html_frame_end();
}
function getOutputEditorValues($aClean)
{
$this->sDescription = $aClean['sDescription'];
}
function update()
{
$oAppData = new appData($this->iScreenshotId, null, $this);
return $oAppData->update();
}
function objectHideDelete()
{
return TRUE;
}
function getDefaultReply()
{
return appData::getDefaultReply();
}
function display()
{
/* STUB */
return TRUE;
}
function objectMakeLink()
{
/* STUB */
return TRUE;
}
function objectMakeUrl()
{
return APPDB_ROOT."appimage.php?iId={$this->iScreenshotId}";
}
function allowAnonymousSubmissions()
{
return FALSE;
}
function objectGetId()
{
return $this->iScreenshotId;
}
}
?>

168
include/session.php Normal file
View File

@@ -0,0 +1,168 @@
<?php
/*
* session.php - session handler functions
* sessions are stored in memcached
* http://www.danga.com/memcached/
*/
class session
{
// defines
var $_server;
var $_expire;
var $_db;
var $name;
var $msg;
// create session object
function session ($name, $server = "127.0.0.1", $expire = 2)
{
// set the connection server
$this->_server = $server;
// set the session and cookie expiration time in days (default 30 days)
$this->_expire = (60 * 60 * 24 * $expire);
// set name for this session
$this->name = $name;
// define options for sessions
ini_set('session.name', $this->name);
ini_set('session.use_cookies', true);
ini_set('session.use_only_cookies', true);
// setup session object
session_set_save_handler(
array(&$this, "_open"),
array(&$this, "_close"),
array(&$this, "_read"),
array(&$this, "_write"),
array(&$this, "_destroy"),
array(&$this, "_gc")
);
// default lifetime on session cookie
session_set_cookie_params(
$this->_expire,
'/'
);
// start the loaded session
session_start();
// make sure we have a valid memcache server connection
if (!$this->_db->getVersion())
{
trigger_error("Unable to Connect to Session Server", E_USER_ERROR);
}
}
// register variables into session (dynamic load and save of vars)
function register ($var)
{
global $$var;
// load $var into memory
if (isset($_SESSION[$var]))
$$var = $_SESSION[$var];
// store var into session
$_SESSION[$var] =& $$var;
}
// destroy session
function destroy ()
{
session_destroy();
}
// add alert message to buffer that will be displayed on the Next page view of the same user in html class
function addmsg ($text, $color = "black")
{
if (!isset($_SESSION['_msg']))
$_SESSION['_msg'] = array();
$_SESSION['_msg'][] = array(
'msg' => $text,
'color' => $color
);
}
// add alert message that will be displayed on the current page output in html class
function alert ($text, $color = "black")
{
$this->msg[] = array(
'msg' => $text,
'color' => $color
);
}
// clear session messages
function purgemsg ()
{
$this->msg[] = array();
$_SESSION['_msg'][] = array();
}
// output msg_buffer and clear it.
function dumpmsgbuffer ()
{
if (isset($_SESSION['_msg']) and is_array($_SESSION['_msg']))
{
foreach ($_SESSION['_msg'] as $alert)
{
$this->msg[] = $alert;
}
}
$_SESSION['_msg'] = array();
}
// connect to session
function _open ($save_path, $session_name)
{
$this->_db = new Memcache;
return $this->_db->connect($this->_server, "11211");
}
// close the session
function _close ()
{
return $this->_db->close();
}
// restore a session from memory
function _read ($id)
{
return $this->_db->get($id);
}
// write the session
function _write ($id, $data)
{
if ($this->_db->get($id))
{
$this->_db->replace($id, $data, null, $this->_expire);
}
else
{
$this->_db->set($id, $data, null, $this->_expire);
}
return true;
}
// Delete the Session
function _destroy ($id)
{
return $this->_db->delete($id);
}
// Garbage Collector (Not Needed for MemCache)
function _gc ($maxlifetime)
{
return true;
}
}
// end session
?>

30
include/sidebar.php Normal file
View File

@@ -0,0 +1,30 @@
<?php
/***********/
/* SideBar */
/***********/
require_once(BASE."include/distribution.php");
require_once(BASE."include/vendor.php");
require_once(BASE."include/util.php");
function global_sidebar_menu()
{
global $aClean;
$g = new htmlmenu("AppDB");
$g->add('Home', BASE.'index.php');
$g->add("Screenshots", BASE."objectManager.php?sClass=screenshot&amp;sTitle=View+Screenshots");
$g->add("Browse Apps", BASE."objectManager.php?sClass=application&amp;".
'sTitle=Browse%20Applications&amp;sOrderBy=appName&amp;bAscending=true');
$g->add('Browse by Developer', BASE.'objectManager.php?sClass=vendor&amp;sTitle=Browse%20by%20Developer');
$g->add("Top 25", BASE."votestats.php");
$g->add("Submit App", BASE."objectManager.php?sClass=application_queue&amp;".
"sTitle=Submit+Application&amp;sAction=add");
$g->add("Help", BASE."help/");
$g->add("Statistics", BASE."appdbStats.php");
$g->add('Distributions ('.distribution::objectGetEntriesCount('accepted').')', BASE.'objectManager.php?sClass=distribution&amp;sTitle=View%20Distributions');
$g->add("Email Us", "mailto:appdb@winehq.org");
$g->done();
}
?>

66
include/sidebar_admin.php Normal file
View File

@@ -0,0 +1,66 @@
<?php
/*****************/
/* sidebar_admin */
/*****************/
require_once(BASE."include/testData.php");
require_once(BASE."include/distribution.php");
function global_admin_menu() {
$g = new htmlmenu("Global Admin");
$g->add("App Queue (".application::objectGetEntriesCount('queued').")",
BASE.'objectManager.php?sClass=application_queue&amp;sState=queued&amp;sTitle='.
'Application%20Queue');
$g->add("Version Queue (".version::objectGetEntriesCount('queued').")",
BASE.'objectManager.php?sClass=version_queue&amp;sState=queued&amp;sTitle='.
'Version%20Queue');
$g->add("Screenshot Queue (".appData::objectGetEntriesCount('queued', "screenshot").")",
BASE.'objectManager.php?sClass=screenshot&amp;sState=queued&amp;sTitle='.
'Screenshot%20Queue');
$g->add("Maintainer Queue (".Maintainer::objectGetEntriesCount('queued').")",
BASE.'objectManager.php?sClass=maintainer&amp;sState=queued&amp;sTitle='.
'Maintainer%20Queue');
$g->add("Test Results Queue (".testData::objectGetEntriesCount('queued').")",
BASE.'objectManager.php?sClass=testData_queue&amp;sState=queued&amp;sTitle='.
'Test%20Results%20Queue');
$g->add("Bug Link Queue (".bug::objectGetEntriesCount('queued').")",
BASE.'objectManager.php?sClass=bug&amp;sState=queued&amp;sTitle='.
'Bug%20Link%20Queue');
$g->addmisc("&nbsp;");
$g->add("Maintainer Entries (".Maintainer::objectGetEntriesCount('accepted').")",
BASE."admin/adminMaintainers.php");
$g->add("Bug Links (".bug::objectGetEntriesCount('accepted').")",
BASE."objectManager.php?sClass=bug&amp;sTitle=".
"Bug%20Links");
$g->add("Test Results (".testData::objectGetEntriesCount('accepted').")",
BASE."objectManager.php?sClass=testData&amp;sTitle=".
"View%20Test%20Results");
$g->add("Users Management", BASE."admin/adminUsers.php");
$g->add("Comments Management", BASE."admin/adminCommentView.php");
$g->add("Screenshots Management", BASE."admin/adminScreenshots.php");
$g->addmisc("&nbsp;");
$g->add("Rejected Applications (".application::objectGetEntriesCount('rejected').")",
BASE.'objectManager.php?sClass=application_queue&amp;sState=rejected&amp;'.
'sTitle=Rejected%20Applications');
$g->add("Rejected Versions (".version::objectGetEntriesCount('rejected').")",
BASE.'objectManager.php?sClass=version_queue&amp;sState=rejected&amp;'.
'sTitle=Rejected%20Versions');
$g->add("Rejected Test Results (".testData::objectGetEntriesCount('rejected').")",
BASE.'objectManager.php?sClass=testData_queue&amp;sState=rejected&amp;'.
'sTitle=Rejected%20Test%20Results');
$g->addmisc("&nbsp;");
$g->add("Add Category", BASE."objectManager.php?sClass=category&amp;sAction=add&amp;sTitle=Add+Category");
$g->add("Add Vendor", BASE."objectManager.php?sClass=vendor&amp;bQueue=".
"false&amp;sAction=add&amp;sTitle=Add%20Vendor");
$g->done();
}
?>

102
include/sidebar_login.php Normal file
View File

@@ -0,0 +1,102 @@
<?php
/*****************/
/* Login SideBar */
/*****************/
require_once(BASE."include/maintainer.php");
require_once(BASE."include/application.php");
require_once(BASE."include/user.php");
require_once(BASE."include/monitor.php");
function global_sidebar_login() {
$g = new htmlmenu("User Menu");
if($_SESSION['current']->isLoggedIn())
{
$g->add("Logout", BASE."account.php?sCmd=logout");
$g->add("Preferences", BASE."preferences.php");
/* if this user maintains any applications list them */
/* in their sidebar */
$apps_user_maintains = Maintainer::getAppsMaintained($_SESSION['current']);
if($apps_user_maintains)
{
$g->add('Maintainership Overview', BASE.'objectManager.php?sClass=maintainerView&iId='.
$_SESSION['current']->iUserId.'&sTitle=Your+Maintained+Apps');
$g->addmisc("");
$g->addmisc("You maintain:\n");
while(list($index, list($appId, $versionId, $superMaintainer)) = each($apps_user_maintains))
{
$oApp = new application($appId);
if($superMaintainer)
$g->add($oApp->sName."*", $oApp->objectMakeUrl(),"center");
else
{
$oVersion = new version($versionId);
$g->add(version::fullName($versionId),
$oVersion->objectMakeUrl(), "center");
}
}
}
/* Display the user's rejected applications */
$iAppsRejected = application::objectGetEntriesCount('rejected');
if($iAppsRejected && !$_SESSION['current']->hasPriv("admin"))
{
$g->add("Review Rejected Apps ($iAppsRejected)", BASE."objectManager.php?".
"sClass=application_queue&amp;bIsQueue=true&amp;bIsRejected=true&amp;sTitle=".
"Rejected+Applications", "center");
}
/* Display the user's rejected versions */
$iVersionsRejected = version::objectGetEntriesCount('rejected');
if($iVersionsRejected && !$_SESSION['current']->hasPriv("admin"))
{
$g->add("Review Rejected Versions ($iVersionsRejected)",
BASE."objectManager.php?sClass=version_queue&amp;bIsRejected=true".
"&amp;bIsQueue=true&amp;sTitle=Rejected+Versions", "center");
}
/* Display the user's rejected test results */
$iTestDataRejected = testData::objectGetEntriesCount('rejected');
if($iTestDataRejected && !$_SESSION['current']->hasPriv("admin"))
$g->add("Review Rejected Test Results ($iTestDataRejected)",
BASE."objectManager.php?sClass=testData_queue&amp;".
"sAction=view&amp;bIsQueue=true&amp;bIsRejected=true&amp;sTitle=".
"Rejected+Test+Results", "center");
$aMonitored = Monitor::getVersionsMonitored($_SESSION['current']);
if($aMonitored)
{
$g->addmisc("");
$g->addmisc("You monitor:\n");
while(list($i, list($iAppId, $iVersionId)) = each($aMonitored))
{
$oVersion = new version($iVersionId);
$g->add(version::fullName($iVersionId), $oVersion->objectMakeUrl(), "center");
}
}
/* Display a link to the user's queued items,
but not for admins, as theirs are auto-accepted */
if(!$_SESSION['current']->hasPriv("admin"))
{
$g->addmisc("");
$g->add("Your queued items", BASE."queueditems.php");
}
} else
{
$g->add("Log in", login_url());
$g->add("Register", BASE."account.php?sCmd=new");
}
$g->done();
}
?>

View File

@@ -0,0 +1,22 @@
<?php
/*****************/
/* sidebar_admin */
/*****************/
function global_maintainer_admin_menu() {
$g = new htmlmenu("Maintainer Admin");
$g->add('View Version Queue ('.version::objectGetEntriesCount('queued').')',
BASE.'objectManager.php?sClass=version_queue&amp;sState=queued&amp;sTitle='.
'Version%20Queue');
$g->add('View Screenshot Queue ('.screenshot::objectGetEntriesCount('queued').')',
BASE.'objectManager.php?sClass=screenshot&amp;sState=queued&amp;sTitle='.
'Screenshot%20Queue');
$g->add('View Test Results Queue ('.testData::objectGetEntriesCount('queued').')',
BASE.'objectManager.php?sClass=testData_queue&amp;sState=queued&amp;sTitle='.
'Test%20Results%20Queue');
$g->done();
}
?>

580
include/table.php Normal file
View File

@@ -0,0 +1,580 @@
<?php
// classes for managing tables and data related to tables
// class for managing the highlighting/inactive state of a row
class TableRowHighlight
{
private $oHighlightColor;
private $oInactiveColor;
// properties to apply to text when highlighted or inactive
private $sTextDecorationHighlight;
private $sTextDecorationInactive;
function TableRowHighlight(color $oHighlightColor, color $oInactiveColor,
$sTextDecorationHighlight = "",
$sTextDecorationInactive = "")
{
$this->oHighlightColor = $oHighlightColor;
$this->oInactiveColor = $oInactiveColor;
$this->sTextDecorationHighlight = $sTextDecorationHighlight;
$this->sTextDecorationInactive = $sTextDecorationInactive;
}
function GetHighlightColor()
{
return $this->oHighlightColor;
}
function GetInactiveColor()
{
return $this->oInactiveColor;
}
function GetTextDecorationHighlight()
{
return $this->sTextDecorationHighlight;
}
function GetTextDecorationInactive()
{
return $this->sTextDecorationInactive;
}
}
class TableRowClick
{
var $oTableRowHighlight;
var $bHasHighlight;
var $shUrl;
function TableRowClick($shUrl)
{
$this->shUrl = $shUrl;
$this->bHasHighlight = false;
$this->oTableRowHighlight = null;
}
function SetHighlight(TableRowHighlight $oTableRowHighlight)
{
$this->oTableRowHighlight = $oTableRowHighlight;
}
function GetString()
{
$sStr = "";
// if we have highlighting output the attributes necessary to enable the javascript tht we use
// to perform the highlighting actions
if($this->oTableRowHighlight)
{
$sStr.= 'onmouseover="ChangeTr(this, true,'.
'\''.$this->oTableRowHighlight->getHighlightColor()->GetHexString().'\','.
'\''.$this->oTableRowHighlight->getInactiveColor()->GetHexString().'\','.
'\''.$this->oTableRowHighlight->getTextDecorationHighlight().'\','.
'\''.$this->oTableRowHighlight->getTextDecorationInactive().'\');"';
$sStr.= ' onmouseout="ChangeTr(this, false,'.
'\''.$this->oTableRowHighlight->getHighlightColor()->GetHexString().'\','.
'\''.$this->oTableRowHighlight->getInactiveColor()->GetHexString().'\','.
'\''.$this->oTableRowHighlight->getTextDecorationHighlight().'\','.
'\''.$this->oTableRowHighlight->getTextDecorationInactive().'\');"';
}
$sStr.= ' onclick="DoNav(\''.$this->shUrl.'\');"';
return $sStr;
}
}
class TableCell
{
private $sCell;
private $sStyle;
private $sClass;
private $sAlign; // align="$sAlign" will be output if this is not null
private $sValign; // valign="$sValign" will be output if this is not null
private $sWidth; // width="$sWidth"
private $sUrl; // wraps the cell contents in an anchor tag if $sUrl is not null
private $bBold; // if true will output the cell contents as bold
// NOTE: We specifically have limited the parameters to the constructor
// to only the contents of the cell. Additional parameters, while
// appearing convienent, make the parameters confusing
// Use accessors to set additional parameters.
function TableCell($sCellContents)
{
$this->sCellContents = $sCellContents;
$this->sStyle = null;
$this->sClass = null;
$this->sAlign = null;
$this->sValign = null;
$this->sWidth = null;
$this->bBold = false;
}
function SetCellContents($sCellContents)
{
$this->sCellContents = $sCellContents;
}
function SetStyle($sStyle)
{
$this->sStyle = $sStyle;
}
function SetClass($sClass)
{
$this->sClass = $sClass;
}
function SetAlign($sAlign)
{
$this->sAlign = $sAlign;
}
function SetValign($sValign)
{
$this->sValign = $sValign;
}
function SetWidth($sWidth)
{
$this->sWidth = $sWidth;
}
function SetCellLink($sUrl)
{
$this->sUrl = $sUrl;
}
function SetBold($bBold)
{
$this->bBold = $bBold;
}
function GetString()
{
$sStr = "<td";
if($this->sClass)
$sStr.=" class=\"".$this->sClass."\"";
if($this->sStyle)
$sStr.=" style=\"".$this->sStyle."\"";
if($this->sAlign)
$sStr.=" align=\"".$this->sAlign."\"";
if($this->sValign)
$sStr.=" valign=\"".$this->sValign."\"";
if($this->sWidth)
$sStr.=" width=\"".$this->sWidth."\"";
$sStr.=">";
// if we have a url, output the start of the anchor tag
if($this->sUrl)
$sStr.='<a href="'.$this->sUrl.'">';
if($this->bBold)
$sStr.='<b>';
// output the contents of the cell
$sStr.=$this->sCellContents;
if($this->bBold)
$sStr.='</b>';
// if we have a url, close the anchor tag
if($this->sUrl)
$sStr.='</a>';
$sStr.="</td>";
return $sStr;
}
}
class TableRow
{
protected $aTableCells; // array that contains the cells for the table row
private $sStyle; // CSS style to be used
private $sClass; // CSS class to be used
private $sValign; // valign="$sValign" - if this variable is set
private $oTableRowClick; // information about whether the table row is clickable etc
function TableRow()
{
$this->aTableCells = array();
$this->sStyle = null;
$this->sClass = null;
$this->sValign = null;
$this->oTableRowClick = null;
}
function AddCell(TableCell $oTableCell)
{
$this->aTableCells[] = $oTableCell;
}
function AddCells($aTableCells)
{
foreach($aTableCells as $oTableCell)
{
$this->AddCell($oTableCell);
}
}
function AddTextCell($sCellText)
{
$this->AddCell(new TableCell($sCellText));
}
function SetStyle($sStyle)
{
$this->sStyle = $sStyle;
}
function SetClass($sClass)
{
$this->sClass = $sClass;
}
function SetValign($sValign)
{
$this->sValign = $sValign;
}
function SetRowClick($oTableRowClick)
{
$this->oTableRowClick = $oTableRowClick;
}
// get a string that contains the html representation
// of this table row
function GetString()
{
// generate the opening of the tr element
$sStr = "<tr";
if($this->sClass)
$sStr.= " class=\"$this->sClass\"";
if($this->sStyle)
$sStr.= " style=\"$this->sStyle\"";
if($this->sValign)
$sStr.= " valign=\"$this->sValign\"";
if($this->oTableRowClick)
$sStr.= " ".$this->oTableRowClick->GetString();
$sStr.= ">"; // close the opening tr
// process the td elements
foreach($this->aTableCells as $oTableCell)
{
$sStr.=$oTableCell->GetString();
}
// close the table row
$sStr.= "</tr>";
return $sStr;
}
function GetClass()
{
return $this->sClass;
}
function GetTableRowClick()
{
return $this->oTableRowClick;
}
}
/* Class for a sortable table row. The user can click on the header for a sortable field, and it
will alternate between sorting that by ascending/descending order and the default sorting */
class TableRowSortable extends TableRow
{
private $aSortVars; /* Array of sort variables. Not all fields have to be sortable.
This is paired with the aTableCells array from TableRow */
function TableRowSortable()
{
$this->aSortVars = array();
$this->TableRow();
}
/* Adds a table cell without sorting */
function AddTableCell(TableCell $oCell)
{
$this->aTableCells[] = $oCell;
$this->aSortVars[] = '';
}
/* Adds a text cell without sorting */
function AddTextCell($shText)
{
$this->AddTableCell(new TableCell($shText));
}
/* Adds a text cell with a sorting var */
function AddSortableTextCell($shText, $sSortVar)
{
$this->aTableCells[] = new TableCell($shText);
$this->aSortVars[] = $sSortVar;
}
/* Sets sorting info on all cells that are sortable */
function SetSortInfo(TableSortInfo $oSortInfo)
{
for($i = 0; $i < sizeof($this->aTableCells); $i++)
{
$sSortVar = $this->aSortVars[$i];
if($sSortVar)
{
$bAscending = TRUE;
if($this->aSortVars[$i] == $oSortInfo->sCurrentSort)
{
if($oSortInfo->bAscending)
$bAscending = FALSE;
else
$sSortVar = '';
$this->aTableCells[$i]->sCellContents .= $oSortInfo->bAscending ?
' &#9650;' : ' &#9660;';
}
$sAscending = $bAscending == TRUE ? 'true': 'false';
$this->aTableCells[$i]->SetCellLink($oSortInfo->shUrl."sOrderBy=$sSortVar&amp;bAscending=$sAscending");
}
}
}
}
/* Container for table sorting info, used to hold the current sort order */
class TableSortInfo
{
var $sCurrentSort;
var $bAscending;
var $shUrl;
function TableSortInfo($shUrl, $sCurrentSort = '', $bAscending = TRUE)
{
$this->sCurrentSort = $sCurrentSort;
$this->shUrl = $shUrl;
$this->bAscending = $bAscending;
}
/* Parses an array of HTTP vars to determine current sort settings.
Optionally checks the sort var against an array of legal values */
function ParseArray($aClean, $aLegalValues = null)
{
$sCurrentSort = key_exists('sOrderBy', $aClean) ? $aClean['sOrderBy'] : '';
if($aLegalValues && array_search($sCurrentSort, $aLegalValues) === FALSE)
return;
$this->sCurrentSort = $sCurrentSort;
$this->bAscending = key_exists('bAscending', $aClean) ?
($aClean['bAscending'] == 'false') ? false : true : true;
}
}
// object manager table row, has additional parameters used by the object manager
// when outputting a table row
//TODO: php5 consider inheriting from HtmlTableRow since this class is really an
// extension of that class
class OMTableRow
{
private $oTableRow;
private $bHasDeleteLink;
private $bCanEdit;
function OMTableRow($oTableRow)
{
$this->oTableRow = $oTableRow;
$this->bHasDeleteLink = false;
$this->bCanEdit = false;
}
function SetHasDeleteLink($bHasDeleteLink)
{
$this->bHasDeleteLink = $bHasDeleteLink;
}
function GetHasDeleteLink()
{
return $this->bHasDeleteLink;
}
function SetRowClickable(TableRowClick $oTableRowClick)
{
$this->oTableRowClick = $oTableRowClick;
}
function SetStyle($sStyle)
{
$this->oTableRow->SetStyle($sStyle);
}
// add a TableCell to an existing row
function AddCell($oTableCell)
{
$this->oTableRow->AddCell($oTableCell);
}
function GetString()
{
return $this->oTableRow->GetString();
}
function GetTableRow()
{
return $this->oTableRow;
}
}
class Table
{
private $oTableRowHeader;
private $aTableRows;
private $sClass;
private $sWidth;
private $iBorder;
private $sAlign; // align="$sAlign" - deprecated in html standards
private $iCellSpacing; // cellspacing="$iCellSpacing"
private $iCellPadding; // cellpadding="$iCellPadding"
function Table()
{
$this->oTableRowHeader = null;
$this->aTableRows = array();
$this->sClass = null;
$this->sWidth = null;
$this->iBorder = null;
$this->sAlign = null;
$this->iCellSpacing = null;
$this->iCellPadding = null;
}
function AddRow($oTableRow)
{
$this->aTableRows[] = $oTableRow;
}
function SetHeader(TableRow $oTableRowHeader)
{
$this->oTableRowHeader = $oTableRowHeader;
}
function SetClass($sClass)
{
$this->sClass = $sClass;
}
function SetWidth($sWidth)
{
$this->sWidth = $sWidth;
}
function SetBorder($iBorder)
{
$this->iBorder = $iBorder;
}
function SetAlign($sAlign)
{
$this->sAlign = $sAlign;
}
function SetCellSpacing($iCellSpacing)
{
$this->iCellSpacing = $iCellSpacing;
}
function SetCellPadding($iCellPadding)
{
$this->iCellPadding = $iCellPadding;
}
function GetString()
{
$sStr = "<table";
if($this->sClass)
$sStr.= ' class="'.$this->sClass.'"';
if($this->sWidth)
$sStr.= ' width="'.$this->sWidth.'"';
if($this->iBorder !== null)
$sStr.= ' border="'.$this->iBorder.'"';
if($this->sAlign)
$sStr.= ' align="'.$this->sAlign.'"';
if($this->iCellSpacing !== null)
$sStr.= ' cellspacing="'.$this->iCellSpacing.'"';
if($this->iCellPadding !== null)
$sStr.= ' cellpadding="'.$this->iCellPadding.'"';
$sStr.= ">"; // close the open table element
if($this->oTableRowHeader)
{
$sStr.="<thead>";
$sStr.= $this->oTableRowHeader->GetString();
$sStr.="</thead>";
}
foreach($this->aTableRows as $oTableRow)
{
$sStr.= $oTableRow->GetString();
}
$sStr.= "</table>";
return $sStr;
}
}
// input is the row index, we alternate colors based on odd or even index rows
// returns a TableRowHighlight instance
function GetStandardRowHighlight($iRowIndex)
{
//set row color
$sColor = ($iRowIndex % 2) ? "color0" : "color1";
$oInactiveColor = new color();
$oInactiveColor->SetColorByName($sColor);
$oHighlightColor = GetHighlightColorFromInactiveColor($oInactiveColor);
$oTableRowHighlight = new TableRowHighlight($oHighlightColor, $oInactiveColor);
return $oTableRowHighlight;
}
// returns a color class instance
function GetHighlightColorFromInactiveColor(color $oInactiveColor)
{
$oHighlightColor = new color($oInactiveColor->iRed,
$oInactiveColor->iGreen,
$oInactiveColor->iBlue);
$oHighlightColor->Add(50);
return $oHighlightColor;
}
?>

480
include/tableve.php Normal file
View File

@@ -0,0 +1,480 @@
<?php
class TableVE {
var $mode;
var $titleField;
var $titleText;
var $numberedTitles;
/*
* mode can be: view, edit, create
*/
function TableVE($mode)
{
$this->mode = $mode;
$this->titleField = "";
$this->titleText = "";
$this->numberedTitles = 0;
}
function test($query)
{
$hResult = query_appdb($query);
$nfields = query_num_fields($hResult);
$nrows = query_num_rows($hResult);
$table = query_field_table($hResult, 0);
echo "Table: $table <br> Fields: $nfields <br> Rows: $nrows <br> <br>\n";
$i = 0;
while($i < $nfields)
{
$type = query_field_type($hResult, $i);
$name = query_field_name($hResult, $i);
$len = query_field_len($hResult, $i);
$flags = query_field_flags($hResult, $i);
echo "$type | $name | $len | $flags <br>\n";
$i++;
}
}
/* this is a bit of a hack,
* we first create an empty entry, and then simply use the
* edit() function to do the rest of the work for us.
*/
function create($query, $table, $idcolumn)
{
$hResult = query_appdb($query);
$id = query_appdb_insert_id();
$new_query = "SELECT * FROM $table WHERE $idcolumn = $id";
$this->edit($new_query);
}
function view($query)
{
//$this->test($query);
$nrows = 0;
$hResult = query_appdb($query);
$nrows = query_num_rows($hResult);
if(debugging())
{
echo "Query returns $nrows rows.";
}
for($i = 0; $i < $nrows; $i++)
{
$this->view_entry($hResult, $i);
echo "<br>\n";
}
}
function view_entry($hResult, $num)
{
$nfields = query_num_fields($hResult);
$fields = query_fetch_array($hResult, MYSQL_BOTH);
$titleValue = $fields[$this->titleField];
$titleText = $this->titleText;
if($this->numberedTitles)
{
// don't want zero-based.
$num++;
$titleText .= " # $num";
}
//echo "<table border=1 bordercolor=black width='80%' cellpadding=0 cellspacing=0>\n";
//echo "<th class='box-title' colspan='2'></th></tr>\n";
//echo "<tr><td>\n";
echo html_frame_start("Viewing $titleValue $titleText","80%","",0);
echo "<table border=0 width='100%' cellspacing=0 cellpadding=2>\n";
for($i = 0; $i < $nfields; $i++)
{
$field = query_fetch_field($hResult, $i);
if(ereg("^impl_(.+)$", $field->table, $arr))
{
if($cur_impl != $arr[1])
echo "<tr><th class='box-label' colspan=2> ".ucfirst($arr[1])." Implementation </th></tr>\n";
$cur_impl = $arr[1];
}
echo "<tr><td width='15%' class='box-label'><b> $field->name </b></td>";
echo "<td class='box-body'>";
$this->view_entry_output_field($field, $fields[$i], 0);
echo "</td></tr>\n";
}
echo "</table>\n";
echo html_frame_end();
}
function edit($query)
{
$hResult = query_appdb($query);
$nrows = query_num_rows($hResult);
echo "<form method=post action='".$_SERVER['PHP_SELF']."'>\n";
for($i = 0; $i < $nrows; $i++)
{
$this->edit_entry($hResult);
echo "<br>\n";
}
echo html_frame_start("Update Database",100);
echo "<input type=submit value='Update Database'>\n";
echo html_frame_end();
echo "</form>\n";
}
function edit_entry($hResult)
{
$nfields = query_num_fields($hResult);
$fields = query_fetch_array($hResult);
echo html_frame_start(ucfirst($this->mode),"80%","",0);
echo "<table border=0 width='100%' cellspacing=0 cellpadding=2>\n";
$cur_impl = null;
for($i = 0; $i < $nfields; $i++)
{
global $testvar;
$field = query_fetch_field($hResult, $i);
$len = query_field_len($hResult, $i);
if(ereg("^impl_(.+)$", $field->table, $arr))
{
if($cur_impl != $arr[1])
echo "<tr><th class='box-label' colspan=2> ".ucfirst($arr[1])." Implementation </th></tr>\n";
$cur_impl = $arr[1];
}
echo "<tr><td width='15%' class='box-label'><b> $field->name &nbsp; </b></td>";
echo "<td class='box-body'>&nbsp;";
$this->edit_entry_output_field($field, $fields[$i], $len);
echo "</td></tr>\n";
}
echo "</table>\n";
echo html_frame_end();
}
// returns a string that contains the option list
function make_option_list($sVarname, $sCvalue, $sTable, $sIdField, $sNameField, $aWhere = null)
{
$sStr = "";
/* We do not allow direct insertion into of SQL code, so the WHERE clause is
is accepted in an array form, where the first element is the variable
and the second is the value it must be equal to */
if($aWhere)
$sWhere = "WHERE ".$aWhere[0]." ='".$aWhere[1]."'";
$hResult = query_parameters("SELECT ?, ? FROM ? $sWhere ORDER BY ?",
$sIdField, $sNameField, $sTable, $sNameField);
if(!$hResult)
return $sStr; // Oops
$sStr.= "<select name='$sVarname'>\n";
$sStr.= "<option value=0>Choose ...</option>\n";
while(list($iId, $sName) = query_fetch_row($hResult))
{
if ($sName == "NONAME")
continue;
if($iId == $sCvalue)
$sStr.= "<option value=$iId selected>$sName\n";
else
$sStr.= "<option value=$iId>$sName\n";
}
$sStr.= "</select>\n";
return $sStr;
}
function edit_entry_output_field($field, $value, $len)
{
static $idx = 0;
$idx++;
if($len > 50)
$len = 50;
$varname = "FIELD_".$field->table."___".$field->name."[]";
echo "<input type=hidden name='TYPE_$varname' value='$field->type'>\n";
if($field->name == "appId" && $field->table != "appFamily")
{
echo $this->make_option_list($varname, $value, "appFamily", "appId", "appName");
return;
}
if($field->name == "vendorId" && $field->table != "vendor")
{
echo $this->make_option_list($varname, $value, "vendor", "vendorId", "vendorName");
return;
}
if($field->name == "catId" && $field->table != "appCategory")
{
echo $this->make_option_list($varname, $value, "appCategory", "catId", "catName");
return;
}
if($field->name == "catParent")
{
echo $this->make_option_list($varname, $value, "appCategory", "catId", "catName");
return;
}
if($field->name == "keywords")
{
echo "<textarea cols=$len rows=3 name='$varname'>".stripslashes($value)."</textarea>\n";
return;
}
switch($field->type)
{
case "string":
case "enum":
case "int":
case "text":
echo "<input type=text size=$len name='$varname' value='".stripslashes($value)."'>\n";
break;
case "blob":
echo "<textarea cols=$len rows=10 name='$varname'>".stripslashes($value)."</textarea>\n";
break;
case "timestamp":
$time = mysqltimestamp_to_unixtimestamp($value);
echo print_date($time);
break;
case "datetime":
$time = mysqldatetime_to_unixtimestamp($value);
echo print_date($time);
break;
default:
echo "$value &nbsp;\n";
break;
}
$this->entry_add_extra($field, $value);
}
function view_entry_output_field($field, $value, $len)
{
if($len > 50)
$len = 50;
//FIXME: need a better way for special cases
if(!$value && $field->name == "comments")
{
echo "none";
return;
}
if(!$value && ($field->name == "location" || $field->name == "quality"))
{
echo "unknown";
return;
}
if($field->name == "lastmodby")
{
$user = new User();
$name = $user->lookup_realname($value);
if(!$name)
$name = "system";
echo "$name ($value)";
return;
}
switch($field->type)
{
case "string":
case "enum":
case "int":
case "blob":
echo "$value &nbsp;\n";
break;
case "timestamp":
$time = mysqltimestamp_to_unixtimestamp($value);
echo print_date($time);
break;
case "datetime":
$time = mysqldatetime_to_unixtimestamp($value);
echo print_date($time);
break;
default:
echo "$value &nbsp;\n";
break;
}
$this->entry_add_extra($field, $value);
}
/*
* add extra stuff to certain fields
*/
function entry_add_extra($field, $value)
{
/*
* add extra stuff to certain fields
*/
if($field->name == "mslink" && $value)
{
echo html_imagebutton("Go!", $value);
}
if($field->name == "apiname")
{
echo html_imagebutton("Wine LXR", "http://twine.codeweavers.com/lxr/ident?i=$value");
echo html_imagebutton("Wine API", "http://www.winehq.com/WineAPI/$value.html");
}
}
/*
* required field for each table.
* When editing a query this field needs to be present in the query
* in order to identify the correct row to update.
*/
var $table_ids = array(
"user_list" => "userid",
"appFamily" => "appId",
"appVersion" => "versionId",
"userExperience" => "uExpId",
"appCategory" => "catId",
"vendor" => "vendorId",
"appNotes" => "noteId"
);
function get_id($name)
{
reset($this->table_ids);
while(list($table, $id) = each($this->table_ids))
{
$r = "^$table$";
//echo "Checking $r against $name <br>\n";
if(ereg($r, $name))
{
//echo "ID for $name -> $id <br>\n";
return $id;
}
}
return null;
}
/**
* update() expects $_POST as argument
* this is where things are getting kinda complex, here we update "
* multiple entries with multiple fields in multiple tables (get it?)
*/
function update($vars)
{
$tables = array();
$fieldnames = array();
$num_entries = 0;
while(list($varname, $arr) = each($vars))
{
if(!ereg("^FIELD_([a-zA-Z_]+)___(.+)$", $varname, $regs))
continue;
$tables[$regs[1]][] = $regs[2];
$fieldnames[$regs[2]] = $arr;
$num_entries = sizeof($arr);
}
while(list($table, $fields) = each($tables))
{
echo "<b> $table (".$this->get_id($table).") </b>";
if($fieldnames[$this->get_id($table)])
echo "OK!";
echo "<br>\n";
for($i = 0; $i < sizeof($fields); $i++)
echo "- $fields[$i] <br>\n";
echo "<br>\n";
}
for($i = 0; $i < $num_entries; $i++)
{
reset($tables);
while(list($table, $fields) = each($tables))
{
$update = "UPDATE $table SET ";
$count = sizeof($fields);
reset($fields);
while(list($idx, $field) = each($fields))
{
$count--;
if($this->table_ids[$table] == $field)
{
continue;
}
$key = "FIELD_".$table."___".$field;
$type = $vars["TYPE_$key"][$i];
if($type == "int")
$update .= "$field = ".$vars[$key][$i];
else
$update .= "$field = '".addslashes($vars[$key][$i])."'";
if($count)
$update .= ", ";
}
$value = $fieldnames[$this->get_id($table)][$i];
$update .= " WHERE ".$this->get_id($table)." = $value";
if(query_appdb($update))
{
addmsg("Database Operation Complete!","green");
}
if(ereg("^impl_.+$", $table))
{
$value = $fieldnames["apiid"][$i];
query_parameters("UPDATE ? SET lastmodby = '?' WHERE apiid = '?'",
$table, $_SESSION['current']->iUserId, $value);
}
}
}
}
function set_title_field($newTitleField)
{
$this->titleField = $newTitleField;
}
function set_title_text($newTitleText)
{
$this->titleText = $newTitleText;
}
function set_numbered_titles()
{
$this->numberedTitles = 1;
}
};
?>

1517
include/testData.php Normal file

File diff suppressed because it is too large Load Diff

242
include/testData_queue.php Normal file
View File

@@ -0,0 +1,242 @@
<?php
class testData_queue
{
var $oTestData;
var $oDistribution;
function testData_queue($iTestId = null, $oRow = null)
{
$this->oTestData = new testData($iTestId, $oRow);
$this->oDistribution = new distribution($this->oTestData->iDistributionId);
}
function create()
{
if(!$this->oTestData->iDistributionId)
{
$this->oDistribution->create();
$this->oTestData->iDistributionId = $this->oDistribution->iDistributionId;
}
return $this->oTestData->create();
}
function purge()
{
$bSuccess = $this->oTestData->purge();
/* We delete the distribution if it has not been approved and is not associated
with any other testData. Otherwise we would have to have a distribution
queue for admins to clean up unused, queued entries */
$this->oDistribution = new distribution($this->oDistribution->iDistributionId);
if(!sizeof($this->oDistribution->aTestingIds) &&
$this->oDistribution->canEdit())
$this->oDistribution->purge();
return $bSuccess;
}
function delete()
{
$bSuccess = $this->oTestData->delete();
/* We delete the distribution if it has not been approved and is not associated
with any other testData. Otherwise we would have to have a distribution
queue for admins to clean up unused, queued entries */
$this->oDistribution = new distribution($this->oDistribution->iDistributionId);
if(!sizeof($this->oDistribution->aTestingIds) &&
$this->oDistribution->canEdit())
$this->oDistribution->delete();
return $bSuccess;
}
function reQueue()
{
$this->oTestData->reQueue();
$this->oDistribution->reQueue();
}
function unQueue()
{
$this->oTestData->unQueue();
/* Avoid a misguiding message about the distribution being unqueued */
if($this->oDistribution->objectGetState() != 'accepted')
$this->oDistribution->unQueue();
}
function reject()
{
$this->oTestData->reject();
}
function update()
{
$this->oTestData->update();
/* If the distribution was already un-queued the form for editing it would
not have been displayed and getOutputEditorValues() wouldn't have
retrieved a valid sName for the distribution. If sName isn't valid
we shouldn't update the distribution */
if($this->oDistribution->sName)
$this->oDistribution->update();
}
function outputEditor()
{
$this->oTestData->outputEditor();
/* If we are processing queued test results with a queued distribution,
we display some additional help here */
if($this->oDistribution->iDistributionId &&
$this->oDistribution->objectGetState() != 'accepted' && $this->canEdit())
{
echo "The user submitted a new distribution, which will be un-queued ".
"together with the test data unless you select an existing one ".
"from the list above.";
}
/* If the testData is already associated with a distribution and the
distribution is un-queued, there is no need to display the
distribution form here */
if(!$this->oTestData->iDistributionId or
$this->oDistribution->objectGetState() != 'accepted')
{
echo html_frame_start("New Distribution", "90%");
$this->oDistribution->outputEditor();
echo html_frame_end();
}
}
function getOutputEditorValues($aClean)
{
$this->oTestData->getOutputEditorValues($aClean);
$this->oDistribution->getOutputEditorValues($aClean);
}
function checkOutputEditorInput($aClean)
{
return $this->oTestData->checkOutputEditorInput($aClean);
}
function objectGetState()
{
return $this->oTestData->objectGetState();
}
function canEdit()
{
return $this->oTestData->canEdit();
}
function mustBeQueued()
{
return $this->oTestData->mustBeQueued();
}
function objectDisplayAddItemHelp()
{
$this->oTestData->objectDisplayAddItemHelp();
}
public static function objectGetDefaultSort()
{
return testData::objectGetDefaultSort();
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "testingId", $bAscending = true)
{
return $this->oTestData->objectGetEntries($sState, $iRows, $iStart, $sOrderBy, $bAscending);
}
function objectGetEntriesCount($sState)
{
return testData::objectGetEntriesCount($sState);
}
function objectGetHeader()
{
return $this->oTestData->objectGetHeader();
}
function objectGetTableRow()
{
return $this->oTestData->objectGetTableRow();
}
function objectDisplayQueueProcessingHelp()
{
$oTest = new testData();
$oTest->objectDisplayQueueProcessingHelp();
}
function objectShowPreview()
{
return $this->oTestData->objectShowPreview();
}
function display()
{
return $this->oTestData->display();
}
function objectMakeUrl()
{
return $this->oTestData->objectMakeUrl();
}
function objectMakeLink()
{
return $this->oTestData->objectMakeLink();
}
function allowAnonymousSubmissions()
{
return testData::allowAnonymousSubmissions();
}
function objectAllowPurgingRejected()
{
return $this->oTestData->objectAllowPurgingRejected();
}
public function objectGetSubmitTime()
{
return $this->oTestData->objectGetSubmitTime();
}
function objectGetItemsPerPage($sState = 'accepted')
{
return testData::objectGetItemsPerPage($sState);
}
function objectGetId()
{
return $this->oTestData->objectGetId();
}
function objectGetSubmitterId()
{
return $this->oTestData->objectGetSubmitterId();
}
function objectGetChildren($bIncludeDeleted = false)
{
return $this->oTestData->objectGetChildren($bIncludeDeleted);
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return $this->oTestData->objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction);
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
return $this->oTestData->objectGetMail($sAction, $bMailSubmitter, $bParentAction);
}
}
?>

558
include/url.php Normal file
View File

@@ -0,0 +1,558 @@
<?php
/***************************************/
/* url class and related functions */
/***************************************/
require_once(BASE."include/util.php");
/**
* Url class for handling urls
*/
class Url {
var $iUrlId;
var $iAppId;
var $iVersionId;
var $sDescription;
var $sUrl;
var $sSubmitTime;
var $sSubmitterId;
var $bQueued;
/**
* Constructor, fetches the url $iUrlId is given.
*/
function Url($iUrlId = null, $oRow = null)
{
if(!$iUrlId && !$oRow)
return;
if(!$oRow)
{
$sQuery = "SELECT appData.*
FROM appData
WHERE type = 'url'
AND id = '?'";
$hResult = query_parameters($sQuery, $iUrlId);
$oRow = query_fetch_object($hResult);
}
// we are working on an existing url
if($oRow)
{
$this->iUrlId = $oRow->id;
$this->sDescription = $oRow->description;
$this->iAppId = $oRow->appId;
$this->iVersionId = $oRow->versionId;
$this->sUrl = Url::normalize($oRow->url);
$this->bQueued = ($oRow->state == 'accepted') ? false : true;
$this->sSubmitTime = $oRow->submitTime;
$this->iSubmitterId = $oRow->submitterId;
}
}
/**
* Creates a new url.
*/
function create($sDescription = null, $sUrl = null, $iVersionId = null,
$iAppId = null, $bSilent = false)
{
global $aClean;
// Security, if we are not an administrator or a maintainer, the url must be queued.
if(($iAppId && !url::canEdit(NULL, $iAppId)) ||
($iVersionId && !url::canEdit($iVersionId)))
$this->bQueued = true;
$hResult = query_parameters("INSERT INTO appData (appId, versionId, type,
description, state, submitTime, submitterId, url)
VALUES ('?', '?', '?', '?', '?', ?, '?', '?')",
$iAppId, $iVersionId, "url", $sDescription,
$this->bQueued ? 'queued' : 'accepted',
"NOW()", $_SESSION['current']->iUserId, $sUrl);
if(!$hResult)
{
addmsg("Error while creating a new url.", "red");
return false;
}
$this->iUrlId = query_appdb_insert_id();
$this->url($this->iUrlId,$this->bQueued);
if(!$bSilent)
$this->SendNotificationMail();
return true;
}
function purge()
{
return $this->delete();
}
/**
* Deletes the url from the database.
* and request its deletion from the filesystem (including the thumbnail).
*/
function delete()
{
$sQuery = "DELETE FROM appData
WHERE id = '?'
AND type = 'url'
LIMIT 1";
if(!$hResult = query_parameters($sQuery, $this->iUrlId))
return false;
return true;
}
/**
* Move url out of the queue.
*/
function unQueue()
{
// If we are not in the queue, we can't move the url out of the queue.
if(!$this->bQueued)
return false;
if(query_parameters("UPDATE appData SET state '?' WHERE id='?'",
'accepted', $this->iUrlId))
{
// we send an e-mail to interested people
$this->mailSubmitter();
$this->SendNotificationMail();
// the url has been unqueued
addmsg("The url has been unqueued.", "green");
}
}
/**
* Update url.
* Returns true on success and false on failure.
*/
function update($sDescription = null, $sUrl = null, $iVersionId = null, $iAppId = null, $bSilent = false)
{
if(!$this->iUrlId)
return FALSE;
$oUrl = new url($this->iUrlId);
if($this->iVersionId && !$iVersionId)
$iVersionId = $this->iVersionId;
$sWhatChanged = "";
if ($sDescription && $sDescription!=$this->sDescription)
{
if (!query_parameters("UPDATE appData SET description = '?' WHERE id = '?'",
$sDescription, $this->iUrlId))
return false;
$sWhatChanged .= "Description was changed from\n ".$this->sDescription."\n to \n".$sDescription.".\n\n";
$this->sDescription = $sDescription;
}
if ($sUrl && $sUrl!=$this->sUrl)
{
if (!query_parameters("UPDATE appData SET url = '?' WHERE id = '?'",
$sUrl, $this->iUrlId))
return false;
$sWhatChanged .= "Url was changed from ".$this->sUrl." to ".$sUrl.".\n\n";
$this->sUrl = $sUrl;
}
if ($iVersionId && $iVersionId!=$oUrl->iVersionId)
{
if (!query_parameters("UPDATE appData SET versionId = '?' WHERE id = '?'",
$iVersionId, $this->iUrlId))
return false;
$oVersionBefore = new Version($this->iVersionId);
$oVersionAfter = new Version($iVersionId);
$sWhatChanged .= "Version was changed from ".$oVersionBefore->sName." to ".$oVersionAfter->sName.".\n\n";
$this->iVersionId = $iVersionId;
$this->iAppId = $oVersionAfter->iAppId;
}
if ($iAppId && $iAppId!=$this->iAppId)
{
if (!query_parameters("UPDATE appData SET appId = '?' WHERE id = '?'",
$iAppId, $this->iUrlId))
return false;
$oAppBefore = new Application($this->iAppId);
$oAppAfter = new Application($iAppId);
$sWhatChanged .= "Application was changed from ".$oAppBefore->sName." to ".$oAppAfter->sName.".\n\n";
$this->iAppId = $iAppId;
}
if($sWhatChanged && !$bSilent)
$this->SendNotificationMail("edit",$sWhatChanged);
return true;
}
function mailSubmitter($bRejected=false)
{
global $aClean;
if($this->iSubmitterId)
{
$sAppName = Application::lookup_name($this->iAppId)." ".Version::lookup_name($this->iVersionId);
$oSubmitter = new User($this->iSubmitterId);
if(!$bRejected)
{
$sSubject = "Submitted url accepted";
$sMsg = "The url you submitted for ".$sAppName." has been accepted.";
} else
{
$sSubject = "Submitted url rejected";
$sMsg = "The url you submitted for ".$sAppName." has been rejected.";
}
$sMsg .= $aClean['sReplyText']."\n";
$sMsg .= "We appreciate your help in making the Application Database better for all users.";
mail_appdb($oSubmitter->sEmail, $sSubject ,$sMsg);
}
}
function SendNotificationMail($bDeleted=false)
{
/* Set variables depending on whether the url is for an app or version */
if($this->iVersionId)
{
$oVersion = new version($this->iVersionId);
$sAppName = version::fullName($this->iVersionId);
$sUrl = $oVersion->objectMakeUrl();
} else
{
$oApp = new application($this->iAppId);
$sAppName = $oApp->sName;
$sUrl = $oApp->objectMakeUrl();
}
if(!$bDeleted)
{
if(!$this->bQueued)
{
$sSubject = "Url for $sAppName added by ".$_SESSION['current']->sRealname;
$sMsg = "$sUrl\n";
if($this->iSubmitterId)
{
$oSubmitter = new User($this->iSubmitterId);
$sMsg .= "This url has been submitted by ".$oSubmitter->sRealname.".";
$sMsg .= "\n";
}
addmsg("The url was successfully added into the database.", "green");
} else // Url queued.
{
$sSubject = "Url for $sAppName submitted by ".
$_SESSION['current']->sRealname;
$sMsg = "$sUrl\n";
$sMsg .= "This url has been queued.";
$sMsg .= "\n";
addmsg("The url you submitted will be added to the database ".
"database after being reviewed.", "green");
}
}
$sEmail = User::get_notify_email_address_list(null, $this->iVersionId);
if($sEmail)
mail_appdb($sEmail, $sSubject ,$sMsg);
}
/* Output an editor for URL fields */
function outputEditor($sFormAction, $oVersion, $oApp = NULL)
{
/* Check for correct permissions */
if(($oVersion && !url::canEdit($oVersion->iVersionId)) ||
($oApp && !url::canEdit(NULL, $oApp->iAppId)))
return FALSE;
if($oVersion)
$hResult = appData::getData($oVersion->iVersionId, "url");
else
$hResult = appData::getData($oApp->iAppId, "url", FALSE);
$sReturn .= html_frame_start("URLs", "90%", "", 0);
$sReturn .= "<form method=\"post\" action=\"$sFormAction\">\n";
$sReturn .= html_table_begin("border=0 cellpadding=5 cellspacing=0 width=100%");
$sReturn .= html_tr(array(
array("<b>Remove</b>", "width=\"90\""),
"<b>Description</b>",
"<b>URL</b>"
),
"color0");
$sReturn .= html_tr(array(
"&nbsp;",
"<input type=\"text\" size=\"45\" name=\"".
"sDescriptionNew\">",
"<input type=\"text\" size=\"45\" name=\"sUrlNew\">"),
"color4");
if($hResult)
{
for($i = 1; $oRow = query_fetch_object($hResult); $i++)
{
$sReturn .= html_tr(array(
"<input type=\"checkbox\" name=\"bRemove$oRow->id\" ".
"value=\"true\">",
"<input type=\"text\" size=\"45\" name=\"".
"sDescription$oRow->id\" value=\"$oRow->description\">",
"<input type=\"text\" size=\"45\" name=\"sUrl$oRow->id\" ".
"value=\"$oRow->url\">"),
($i % 2) ? "color0" : "color4");
}
}
if($oVersion)
$iAppId = $oVersion->iAppId;
else
$iAppId = $oApp->iAppId;
$sReturn .= html_table_end();
$sReturn .= "<div align=\"center\"><input type=\"submit\" value=\"".
"Update URLs\" name=\"sSubmit\"></div>\n";
if($oVersion)
$sReturn .=" <input type=\"hidden\" name=\"iVersionId\" ".
"value=\"$oVersion->iVersionId\">\n";
$sReturn .= "<input type=\"hidden\" name=\"iAppId\" ".
"value=\"$iAppId\">\n";
$sReturn .= "</form>\n";
$sReturn .= html_frame_end("&nbsp;");
return $sReturn;
}
/* Process data from a URL form */
function ProcessForm($aValues)
{
/* Check that we are processing a Download URL form */
if($aValues["sSubmit"] != "Update URLs")
return FALSE;
/* Check permissions */
if(($aValues['iVersionId'] && !url::canEdit($aValues["iVersionId"])) ||
(!$aValues['iVersionId'] && !url::canEdit(NULL, $aValues['iAppId'])))
return FALSE;
if($aValues["iVersionId"])
{
if(!($hResult = query_parameters("SELECT COUNT(*) as num FROM appData
WHERE TYPE = '?' AND versionId = '?'",
"url", $aValues["iVersionId"])))
return FALSE;
} else
{
if(!($hResult = query_parameters("SELECT COUNT(*) as num FROM appData
WHERE TYPE = '?' AND appId = '?'",
"url", $aValues["iAppId"])))
return FALSE;
}
if(!($oRow = query_fetch_object($hResult)))
return FALSE;
$num = $oRow->num;
/* Update URLs. Nothing to do if none are present in the database */
if($num)
{
if($aValues['iVersionId'])
{
if(!$hResult = appData::getData($aValues["iVersionId"], "url"))
return FALSE;
} else
{
if(!$hResult = appData::getData($aValues['iAppId'], "url", FALSE))
return FALSE;
}
while($oRow = query_fetch_object($hResult))
{
$url = new url($oRow->id);
/* Remove URL */
if($aValues["bRemove$oRow->id"])
{
if(!$url->delete(TRUE))
return FALSE;
$sWhatChangedRemove .= "Removed\nURL: $oRow->url\n".
"Description: $oRow->description\n\n";
}
/* Change description/URL */
if(($aValues["sDescription$oRow->id"] != $oRow->description or
$aValues["sUrl$oRow->id"] != $oRow->url) &&
$aValues["sDescription$oRow->id"] && $aValues["sUrl$oRow->id"])
{
if(!$url->update($aValues["sDescription$oRow->id"],
$aValues["sUrl$oRow->id"], $aValues["iVersionId"],
$aValues["iVersionId"] ? 0 : $aValues["iAppId"], TRUE))
return FALSE;
$sWhatChangedModify .= "Modified\nOld URL: $oRow->url\nOld ".
"Description: $oRow->description\nNew URL: ".
$aValues["sUrl$oRow->id"]."\nNew Description: ".
$aValues["sDescription$oRow->id"]."\n\n";
}
}
}
/* Insert new URL */
if($aValues["sDescriptionNew"] && $aValues["sUrlNew"])
{
$url = new Url();
if(!$url->create($aValues["sDescriptionNew"], $aValues["sUrlNew"],
$aValues["iVersionId"] ? $aValues["iVersionId"] : "0",
$aValues["iVersionId"] ? "0" : $aValues["iAppId"], TRUE))
return FALSE;
$sWhatChanged = "Added\nURL: ".$aValues["sUrlNew"]."\nDescription: ".
$aValues["sDescriptionNew"]."\n\n";
}
$sWhatChanged .= "$sWhatChangedRemove$sWhatChangedModify";
if($aValues["iVersionId"])
$sEmail = User::get_notify_email_address_list($aValues['iVersionId']);
else
$sEmail = User::get_notify_email_address_list($aValues['iAppId']);
if($sWhatChanged && $sEmail)
{
$oApp = new Application($aValues["iAppId"]);
if($aValues["iVersionId"])
{
$oVersion = new Version($aValues["iVersionId"]);
$sVersionName = " $oVersion->sName";
}
$sSubject = "Links for $oApp->sName$sVersionName updated by ".
$_SESSION['current']->sRealname;
$sMsg = $aValues["iVersionId"] ?
$oVersion->objectMakeUrl() :
$oApp->objectMakeUrl();
$sMsg .= "\n\n";
$sMsg .= "The following changed were made\n\n";
$sMsg .= "$sWhatChanged\n\n";
mail_appdb($sEmail, $sSubject, $sMsg);
}
return TRUE;
}
function canEdit($iVersionId = NULL, $iAppId = NULL)
{
if($_SESSION['current']->hasPriv("admin"))
return TRUE;
else if($iVersionId)
{
$oVersion = new version($iVersionId);
return $oVersion->canEdit();
} else if($iAppId)
{
$oApp = new application($iAppId);
return $oApp->canEdit();
} else
return FALSE;
}
/* Display links for a given version/application */
function display($iVersionId, $iAppId = NULL)
{
if($iVersionId)
{
if(!($hResult = appData::getData($iVersionId, "url")))
return FALSE;
} else
{
if(!($hResult = appData::getData($iAppId, "url", FALSE)))
return FALSE;
}
$sReturn = '';
for($i = 0; $oRow = query_fetch_object($hResult); $i++)
{
// create a url object
$oUrl = new Url(null, $oRow);
$sReturn .= html_tr(array(
"<b>Link</b>",
"<a href=\"$oUrl->sUrl\">$oUrl->sDescription</a>"),
"color1");
}
return $sReturn;
}
function objectGetId()
{
return $this->iUrlId;
}
function objectGetSubmitterId()
{
return $this->iSubmitterId;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
/* We don't do this at the moment */
return array(null, null, null);
}
public function objectGetParent($sClass = '')
{
$oAppData = new appData($this->iUrlId, null, $this);
return $oAppData->objectGetParent();
}
public function objectSetParent($iNewId, $sClass = '')
{
if($this->iVersionId)
$this->iVersionId = $iNewId;
else
$this->iAppId = $iNewId;
}
function objectGetChildren($bIncludeDeleted = false)
{
return array();
}
// if a url lacks "://" assume the url is an http one
// and prepend "http://"
function normalize($sTheUrl)
{
// return if we have an empty string
if($sTheUrl == "")
return $sTheUrl;
// if we already have "://" in the url
// we can leave the url alone
if(strpos($sTheUrl, "://") === false)
{
// assume this is a website and prepend "http://"
return "http://".$sTheUrl;
} else
{
// leave the url alone
return $sTheUrl;
}
}
}
?>

866
include/user.php Normal file
View File

@@ -0,0 +1,866 @@
<?php
/************************************/
/* user class and related functions */
/************************************/
require_once(BASE."include/version.php");
require_once(BASE."include/maintainer.php");
require_once(BASE."include/util.php");
define("SUCCESS", 0);
define("USER_CREATE_EXISTS", 1);
define("USER_CREATE_FAILED", 2);
define("USER_LOGIN_FAILED", 3);
define("USER_UPDATE_FAILED", 4);
define("USER_UPDATE_FAILED_EMAIL_EXISTS", 5); /* user updating to an email address that is already in use */
define("USER_UPDATE_FAILED_NOT_LOGGED_IN", 6); /* user::update() called but user not logged in */
/**
* User class for handling users
*/
class User {
var $iUserId;
var $sEmail;
var $sRealname;
var $sStamp;
var $sDateCreated;
var $sWineRelease;
var $bInactivityWarned;
/**
* Constructor.
* If $iUserId is provided, logs in user.
*/
function User($iUserId="")
{
$this->sRealname = "an anonymous user";
if(is_numeric($iUserId))
{
$sQuery = "SELECT *
FROM user_list
WHERE userId = '?'";
$hResult = query_parameters($sQuery, $iUserId);
$oRow = query_fetch_object($hResult);
if($oRow)
{
$this->iUserId = $oRow->userid;
$this->sEmail = $oRow->email;
$this->sRealname = $oRow->realname;
$this->sStamp = $oRow->stamp;
$this->sDateCreated = $oRow->created;
$this->sWineRelease = $oRow->CVSrelease;
$this->bInactivityWarned = $oRow->inactivity_warned;
}
}
return $this->isLoggedIn();
}
/**
* Logs in an user using e-mail and password.
*/
function login($sEmail, $sPassword)
{
$sQuery = "SELECT *
FROM user_list
WHERE email = '?' AND password = ";
$sMysqlSHAPasswordPart = "SHA1('?');";
$sMysqlPasswordPart = "password('?');";
$sMysql40xPasswordPart = "old_password('?');";
// if true we used an old style password and we need to
// update the users password to the new style
$bUsedOldStylePassword = false;
$oRow = null; // null out the row object
// if we aren't logged in yet
// try to login with the mysql sha1() value of the password
if(!$oRow)
{
$hResult = query_parameters($sQuery.$sMysqlSHAPasswordPart,
$sEmail, $sPassword);
$oRow = query_fetch_object($hResult);
}
// if we aren't logged in yet
// try to login with the mysql password() value of the password
if(!$oRow)
{
$hResult = query_parameters($sQuery.$sMysqlPasswordPart,
$sEmail, $sPassword);
$oRow = query_fetch_object($hResult);
if($oRow) $bUsedOldStylePassword = true;
}
// if we aren't logged in yet
// try to login with the mysql old_password() value of the password
if(!$oRow)
{
// make sure we have a newer version, older versions may not
$sResult = mysql_get_server_info();
$fVersion = substr($sResult, 0, 3);
// if we have a newer version of mysql, try with the 'old_password()' function
if($fVersion >= 4.1)
{
$hResult = query_parameters($sQuery.$sMysql40xPasswordPart,
$sEmail, $sPassword);
$oRow = query_fetch_object($hResult);
if($oRow) $bUsedOldStylePassword = true;
}
}
if($oRow)
{
$this->iUserId = $oRow->userid;
$this->sEmail = $oRow->email;
$this->sRealname = $oRow->realname;
$this->sStamp = $oRow->stamp;
$this->sDateCreated = $oRow->created;
$this->sWineRelease = $oRow->CVSrelease;
// if we used an old style password, update the users password
if($bUsedOldStylePassword)
{
$this->update_password($sPassword);
}
}
if($this->isLoggedIn())
{
// Update timestamp and clear the inactivity flag if it was set
query_parameters("UPDATE user_list SET stamp = ?, inactivity_warned = '?' WHERE userid='?'",
"NOW()", "false", $this->iUserId);
/* set the session variable for the current user to this user object */
$_SESSION['current'] = $this;
return SUCCESS;
}
/* destroy all session variables since we failed to login */
$GLOBALS['session']->destroy();
return USER_LOGIN_FAILED;
}
function logout()
{
/* destroy all session variables since we are logging out */
$GLOBALS['session']->destroy();
}
/*
* Creates a new user.
* returns SUCCESS on success, USER_CREATE_EXISTS if the user already exists
*/
function create($sEmail, $sPassword, $sRealname, $sWineRelease)
{
if(User::exists($sEmail))
{
return USER_CREATE_EXISTS;
} else
{
$hResult = query_parameters("INSERT INTO user_list (realname, email, CVSrelease, password, stamp,".
"created) VALUES ('?', '?', '?', SHA1('?'), ?, ?)",
$sRealname, $sEmail, $sWineRelease, $sPassword, "NOW()", "NOW()");
if(!$hResult) return USER_CREATE_FAILED;
$retval = $this->login($sEmail, $sPassword);
if($retval == SUCCESS)
$this->setPref("comments:mode", "threaded"); /* set the users default comments:mode to threaded */
$this->logout();
return $retval;
}
}
/**
* Update User Account;
*/
function update()
{
if(!$this->isLoggedIn()) return USER_UPDATE_FAILED_NOT_LOGGED_IN;
/* create an instance of ourselves so we can see what has changed */
$oUser = new User($this->iUserId);
if($this->sEmail && ($this->sEmail != $oUser->sEmail))
{
/* make sure this email isn't already in use */
if(User::exists($this->sEmail))
{
addMsg("An account with this e-mail exists already.","red");
return USER_UPDATE_FAILED_EMAIL_EXISTS;
}
if (!query_parameters("UPDATE user_list SET email = '?' WHERE userid = '?'",
$this->sEmail, $this->iUserId))
return USER_UPDATE_FAILED;
}
if ($this->sRealname && ($this->sRealname != $oUser->sRealname))
{
if (!query_parameters("UPDATE user_list SET realname = '?' WHERE userid = '?'",
$this->sRealname, $this->iUserId))
return USER_UPDATE_FAILED;
}
if ($this->sWineRelease && ($this->sWineRelease != $oUser->sWineRelease))
{
if (!query_parameters("UPDATE user_list SET CVSrelease = '?' WHERE userid = '?'",
$this->sWineRelease, $this->iUserId))
return USER_UPDATE_FAILED;
}
return SUCCESS;
}
/**
* NOTE: we can't update the users password like we can update other
* fields such as their email or username because the password is hashed
* in the database so we can't keep the users password in a class member variable
* and use update() because we can't check if the password changed without hashing
* the newly supplied one
*/
function update_password($sPassword)
{
if($sPassword)
{
if (query_parameters("UPDATE user_list SET password = SHA1('?') ".
"WHERE userid = '?'",
$sPassword, $this->iUserId))
return true;
}
return false;
}
/**
* Removes the current, or specified user and preferences from the database.
* returns true on success and false on failure.
*/
function delete()
{
$hResult2 = query_parameters("DELETE FROM user_privs WHERE userid = '?'", $this->iUserId);
$hResult3 = query_parameters("DELETE FROM user_prefs WHERE userid = '?'", $this->iUserId);
$hResult4 = query_parameters("DELETE FROM appVotes WHERE userid = '?'", $this->iUserId);
$hResult5 = Maintainer::deleteMaintainer($this);
$hResult6 = query_parameters("DELETE FROM appComments WHERE userId = '?'", $this->iUserId);
return($hResult = query_parameters("DELETE FROM user_list WHERE userid = '?'", $this->iUserId));
}
/**
* Get a preference for the current user.
*/
function getPref($sKey, $sDef = null)
{
if(!$this->isLoggedIn() || !$sKey)
return $sDef;
$hResult = query_parameters("SELECT * FROM user_prefs WHERE userid = '?' AND name = '?'",
$this->iUserId, $sKey);
if(!$hResult || query_num_rows($hResult) == 0)
return $sDef;
$oRow = query_fetch_object($hResult);
return $oRow->value;
}
/**
* Set a preference for the current user.
*/
function setPref($sKey, $sValue)
{
if(!$this->isLoggedIn() || !$sKey || !$sValue)
return false;
$hResult = query_parameters("DELETE FROM user_prefs WHERE userid = '?' AND name = '?'",
$this->iUserId, $sKey);
$hResult = query_parameters("INSERT INTO user_prefs (userid, name, value) VALUES".
"('?', '?', '?')", $this->iUserId, $sKey, $sValue);
return $hResult;
}
/**
* Check if this user has $priv.
*/
function hasPriv($sPriv)
{
if(!$this->isLoggedIn() || !$sPriv)
return false;
$hResult = query_parameters("SELECT * FROM user_privs WHERE userid = '?' AND priv = '?'",
$this->iUserId, $sPriv);
if(!$hResult)
return false;
return query_num_rows($hResult);
}
/* Check if this user is a maintainer of a given appId/versionId */
function isMaintainer($iVersionId=null)
{
return Maintainer::isUserMaintainer($this, $iVersionId);
}
/* Check if this user is a maintainer of a given appId/versionId */
function isSuperMaintainer($iAppId=null)
{
return Maintainer::isUserSuperMaintainer($this, $iAppId);
}
function addPriv($sPriv)
{
if(!$this->isLoggedIn() || !$sPriv)
return false;
if($this->hasPriv($sPriv))
return true;
$hResult = query_parameters("INSERT INTO user_privs (userid, priv) VALUES".
" ('?', '?')", $this->iUserId, $sPriv);
return $hResult;
}
function delPriv($sPriv)
{
if(!$this->isLoggedIn() || !$sPriv)
return false;
$hResult = query_parameters("DELETE FROM user_privs WHERE userid = '?' AND priv = '?'",
$this->iUserId, $sPriv);
return $hResult;
}
/**
* Checks if the current user is valid.
*/
function isLoggedIn()
{
return $this->iUserId;
}
/**
* Checks if user should see debugging infos.
*/
function showDebuggingInfos()
{
return (($this->isLoggedIn() && $this->getPref("debug") == "yes") || APPDB_DEBUG == 1);
}
/**
* Checks if user wants to get e-mails.
*/
function wantsEmail()
{
return ($this->isLoggedIn() && $this->getPref("send_email","yes")=="yes");
}
function isAppSubmitter($iAppId)
{
$hResult = query_parameters("SELECT appId FROM appFamily
WHERE submitterId = '?'
AND appId = '?'",
$this->iUserId, $iAppId);
if(query_num_rows($hResult))
return true;
else
return false;
}
function isVersionSubmitter($iVersionId)
{
$hResult = query_parameters("SELECT appVersion.versionId FROM appVersion, appFamily
WHERE appFamily.appId = appVersion.appId
AND appVersion.submitterId = '?'
AND appVersion.versionId = '?'",
$this->iUserId, $iVersionId);
if(query_num_rows($hResult))
return true;
else
return false;
}
/* if this user has data associated with them we will return true */
/* otherwise we return false */
function hasDataAssociated()
{
$hResult = query_parameters("SELECT count(userId) as c FROM appComments WHERE userId = '?'",
$this->iUserId);
$oRow = query_fetch_object($hResult);
if($oRow->c != 0) return true;
if($this->isMaintainer() || $this->isSuperMaintainer())
return true;
$hResult = query_parameters("SELECT count(userId) as c FROM appVotes WHERE userId = '?'",
$this->iUserId);
$oRow = query_fetch_object($hResult);
if($oRow->c != 0) return true;
return false;
}
/* warn the user that their account has been marked as inactive */
function warnForInactivity()
{
/* we don't want to warn users that have data associated with them */
if($this->hasDataAssociated())
{
return false;
}
if($this->isMaintainer())
{
$sSubject = "Warning: inactivity detected";
$sMsg = "You didn't log in in the past six months to the AppDB.\r\n";
$sMsg .= "As a maintainer we would be pleased to see you once in a while.\r\n";
$sMsg .= "Please log in or you will lose your maintainer's abilities in one month.\r\n";
} else
{
$sSubject = "Warning: inactivity detected";
$sMsg = "You didn't log in in the past six months to the AppDB.\r\n";
$sMsg .= "Please log in or your account will automatically be deleted in one month.\r\n";
}
$sMsg .= APPDB_ROOT."account.php?sCmd=login\r\n";
mail_appdb($this->sEmail, $sSubject, $sMsg);
/* mark this user as being inactive and set the appropriate timestamp */
$sQuery = "update user_list set inactivity_warned='true', inactivity_warn_stamp=NOW() where userid='?'";
query_parameters($sQuery, $this->iUserId);
return true;
}
/**
* Creates a new random password.
*/
function generate_passwd($pass_len = 10)
{
$nps = "";
mt_srand ((double) microtime() * 1000000);
while (strlen($nps)<$pass_len)
{
$c = chr(mt_rand (0,255));
if (eregi("^[a-z0-9]$", $c)) $nps = $nps.$c;
}
return ($nps);
}
/**
* Check if a user exists.
* returns the userid if the user exists
*/
function exists($sEmail)
{
$hResult = query_parameters("SELECT userid FROM user_list WHERE email = '?'",
$sEmail);
if(!$hResult || query_num_rows($hResult) != 1)
{
return 0;
} else
{
$oRow = query_fetch_object($hResult);
return $oRow->userid;
}
}
/**
* Get the number of users in the database
* The parameters are only included for compatibility; we don't queue users
*/
function objectGetEntriesCount($bQueued = null, $bRejected = null)
{
$hResult = query_parameters("SELECT count(*) as num_users FROM user_list;");
$oRow = query_fetch_object($hResult);
return $oRow->num_users;
}
/**
* Get the number of active users within $days of the current day
*/
function active_users_within_days($days)
{
$hResult = query_parameters("SELECT count(*) as num_users FROM user_list WHERE stamp >= DATE_SUB(CURDATE(), interval '?' day);",
$days);
$oRow = query_fetch_object($hResult);
return $oRow->num_users;
}
/**
* Get the count of users who have been warned for inactivity and are
* pending deletion after the X month grace period
*/
function get_inactive_users_pending_deletion()
{
/* retrieve the number of users that have been warned and are pending deletion */
$hResult = query_parameters("select count(*) as count from user_list where inactivity_warned = 'true'");
$oRow = query_fetch_object($hResult);
return $oRow->count;
}
/**
* Get the email address of people to notify for this appId and versionId.
*/
function get_notify_email_address_list($iAppId = null, $iVersionId = null)
{
$aUserId = array();
$sRetval = "";
/*
* Retrieve version maintainers.
*/
$hResult = Maintainer::getMaintainersForAppIdVersionId($iAppId, $iVersionId);
if($hResult)
{
if(query_num_rows($hResult) > 0)
{
while($oRow = query_fetch_object($hResult))
$aUserId[] = $oRow->userId;
}
}
/*
* Retrieve version Monitors.
*/
/*
* If versionId was supplied we fetch superMonitors of application and Monitors of version.
*/
if($iVersionId)
{
$hResult = query_parameters("SELECT appMonitors.userId
FROM appMonitors, appVersion
WHERE appVersion.appId = appMonitors.appId
AND appVersion.versionId = '?'",
$iVersionId);
}
/*
* If versionId was not supplied we fetch superMonitors of application and Monitors of all versions.
*/
elseif($iAppId)
{
$hResult = query_parameters("SELECT userId
FROM appMonitors
WHERE appId = '?'",
$iAppId);
}
if($hResult)
{
if(query_num_rows($hResult) > 0)
{
while($oRow = query_fetch_object($hResult))
$aUserId[] = $oRow->userId;
}
}
/*
* Retrieve administrators.
*/
$hResult = query_parameters("SELECT * FROM user_privs WHERE priv = 'admin'");
if(query_num_rows($hResult) > 0)
{
while($oRow = query_fetch_object($hResult))
{
$i = array_search($oRow->userid, $aUserId);
// if we didn't find this entry in the $aUserId
// array then we should add it
if($i === false)
$aUserId[] = $oRow->userid;
}
}
// go through the email entries and only add the emails for the users
// that want to receive it
if (sizeof($aUserId) > 0)
{
foreach($aUserId as $iUserId)
{
$oUser = new User($iUserId);
if ($oUser->wantsEmail())
$sRetval .= $oUser->sEmail." ";
}
}
return $sRetval;
}
/************************/
/* Permission functions */
/************************/
/**
* Returns true or false depending on whether the user can view the image
*/
function canViewImage($iImageId)
{
$oScreenshot = new Screenshot($iImageId);
if(!$oScreenshot->bQueued ||
($oScreenshot->bQueued && ($this->hasPriv("admin") ||
$this->isMaintainer($oScreenshot->iVersionId) ||
$this->isSuperMaintainer($oScreenshot->iAppId))))
return true;
return false;
}
/***************************/
/* application permissions */
function canViewApplication($oApp)
{
/* If there is no id the app is not in the database, which means the current user must have created the object */
if(!$oApp->iAppId)
return true;
/* if the application isn't queued */
if($oApp->objectGetState() == 'accepted')
return true;
if($this->hasPriv("admin"))
return true;
/* if this user is the submitter and the application is queued */
if(($this->iUserId == $oApp->iSubmitterId) &&
($oApp->objectGetState() != 'accepted'))
return true;
return false;
}
/**
* Does the user have permission to modify this application?
*/
function canModifyApplication($oApp)
{
if($this->hasPriv("admin"))
return true;
/* is this user a super maintainer of this app? */
if($this->isSuperMaintainer($oApp->iAppId))
return true;
/* if the user is the submitter of the application */
/* and the application is still queued */
/* the user can modify the app */
if(($this->iUserId == $oApp->iSubmitterId) &&
($oApp->objectGetState() != 'accepted'))
return true;
return false;
}
/**
* Can this user create applications?
*/
function canCreateApplication()
{
return $this->isLoggedIn();
}
/**
* Returns 'true' if the current user has the permission to delete
* this application, 'false' otherwise
*/
function canDeleteApplication($oApp)
{
if($this->hasPriv("admin"))
return true;
/* is this the user that submitted the application and is still queued */
if(($oApp->objectGetState() != 'accepted') && ($oApp->iSubmitterId == $this->iUserId))
return true;
return false;
}
/* Can this user unQueue applications? */
function canUnQueueApplication()
{
return $this->hasPriv("admin");
}
/* Can this user Requeue an application? */
function canRequeueApplication($oApp)
{
if($oApp->objectGetState() == 'accepted')
return false;
if($this->hasPriv("admin"))
return true;
if(($oApp->objectGetState() != 'accepted') && ($oApp->iSubmitterId == $this->iUserId))
return true;
return false;
}
/* Can the user reject application? */
function canRejectApplication()
{
return $this->hasPriv("admin");
}
/***********************/
/* version permissions */
function canViewVersion($oVersion)
{
/* If there is no id that means data must have been generated by the user */
if(!$oVersion->iVersionId)
return true;
/* if the version isn't queued */
if($oVersion->objectGetState() == 'accepted')
return true;
if($this->hasPriv("admin"))
return true;
/* if the user is the submitter and the version is still queued */
if(($this->iUserId == $oVersion->iSubmitterId) &&
($oVersion->objectGetState() != 'accepted'))
return true;
/* if this user supermaintains the application this version belongs to */
if($this->isSupermaintainer($oVersion->iAppId))
return true;
return false;
}
/**
* Does the user have permission to modify on this version?
*/
function hasAppVersionModifyPermission($oVersion)
{
if(!$this->isLoggedIn())
return false;
if($this->hasPriv("admin"))
return true;
if($this->isSuperMaintainer($oVersion->iAppId))
return true;
if($this->isMaintainer($oVersion->iVersionId))
return true;
/* the version is queued and the user is the submitter */
if(($oVersion->objectGetState() != 'accepted') && ($this->iUserId == $oVersion->iSubmitterId))
return true;
return false;
}
/**
* Can this user create a version?
*/
function canCreateVersion()
{
return $this->isLoggedIn();
}
/**
* Returns 'true' if the current user has the permission to delete
* this version, 'false' otherwise
*/
function canDeleteVersion($oVersion)
{
if($this->hasPriv("admin"))
return true;
/* if the app is anything other than not queued and if the user is the submitter */
/* then allow the user to delete the app */
if(($oVersion->objectGetState() != 'accepted') && ($oVersion->iSubmitterId == $this->iUserId))
return true;
/* is this user a supermaintainer of the application this version is under? */
if($this->isSuperMaintainer($oVersion->iAppId))
return true;
return false;
}
/**
* Can the user unqueue this version?
*/
function canUnQueueVersion($oVersion)
{
if($this->hasPriv("admin"))
return true;
if($this->hasAppVersionModifyPermission($oVersion))
return true;
return false;
}
/**
* Can the user reject this version?
*/
function canRejectVersion($oVersion)
{
if($this->hasPriv("admin"))
return true;
if($this->hasAppVersionModifyPermission($oVersion))
return true;
return false;
}
/**
* Can the user reject this version?
*/
function canRequeueVersion($oVersion)
{
if($this->hasPriv("admin"))
return true;
if($this->hasAppVersionModifyPermission($oVersion))
return true;
if(($this->iUserId == $oVersion->iSubmitterId) &&
($oVersion->objectGetState() != 'accepted'))
return true;
return false;
}
function objectMakeUrl()
{
if(!$this->iUserId)
return;
$sUrl = BASE."contact.php?iRecipientId=$this->iUserId";
return $sUrl;
}
function objectMakeLink()
{
if(!$this->iUserId)
return $this->sRealname;
$sLink = "<a href=\"".$this->objectMakeUrl()."\">$this->sRealname</a>";
return $sLink;
}
}
?>

1073
include/util.php Normal file

File diff suppressed because it is too large Load Diff

485
include/vendor.php Normal file
View File

@@ -0,0 +1,485 @@
<?php
/**********************************/
/* this class represents a vendor */
/**********************************/
/**
* Vendor class for handling developers.
*/
class Vendor {
var $iVendorId;
var $sName;
var $sWebpage;
private $sState;
var $aApplicationsIds; // an array that contains the appId of every application linked to this vendor
/**
* constructor, fetches the data.
*/
function Vendor($iVendorId = null, $oRow = null)
{
// we are working on an existing vendor
if(!$iVendorId && !$oRow)
return;
if(!$oRow)
{
/*
* We fetch the data related to this vendor.
*/
$sQuery = "SELECT *
FROM vendor
WHERE vendorId = '?'";
if($hResult = query_parameters($sQuery, $iVendorId))
$oRow = query_fetch_object($hResult);
}
if($oRow)
{
$this->iVendorId = $oRow->vendorId;
$this->sName = $oRow->vendorName;
$this->sWebpage = $oRow->vendorURL;
$this->sState = $oRow->state;
}
/*
* We fetch applicationsIds.
*/
$sQuery = "SELECT appId
FROM appFamily
WHERE vendorId = '?' ORDER by appName";
if($hResult = query_parameters($sQuery, $this->iVendorId))
{
while($oRow = query_fetch_object($hResult))
{
$this->aApplicationsIds[] = $oRow->appId;
}
}
}
/**
* Creates a new vendor.
*
* NOTE: If creating a vendor with the same name as an existing vendor
* we retrieve the existing vendors information and return true,
* even though we didn't create the vendor, this makes it easier
* for the user of the vendor class.
*/
function create()
{
/* Check for duplicates */
$hResult = query_parameters("SELECT * FROM vendor WHERE vendorName = '?'",
$this->sName);
if($hResult && $oRow = query_fetch_object($hResult))
{
if(query_num_rows($hResult))
{
$this->vendor($oRow->vendorId);
/* Even though we did not create a new vendor, the caller is provided
with an id and can proceed as normal, so we return TRUE */
return TRUE;
}
}
$hResult = query_parameters("INSERT INTO vendor (vendorName, vendorURL, state) ".
"VALUES ('?', '?', '?')",
$this->sName, $this->sWebpage,
$this->mustBeQueued() ? 'queued' : 'accepted');
if($hResult)
{
$this->iVendorId = query_appdb_insert_id();
$this->vendor($this->iVendorId);
return true;
}
else
{
addmsg("Error while creating a new developer.", "red");
return false;
}
}
/**
* Un-queue vendor
* Returns TRUE or FALSE
*/
function unQueue()
{
$hResult = query_parameters("UPDATE vendor SET state = '?' WHERE vendorId = '?'",
'accepted', $this->iVendorId);
if(!$hResult)
return FALSE;
$this->sState = 'accepted';
return TRUE;
}
/**
* Update vendor.
* Returns true on success and false on failure.
*/
function update()
{
if(!$this->iVendorId)
return $this->create();
if($this->sName)
{
if (!query_parameters("UPDATE vendor SET vendorName = '?' WHERE vendorId = '?'",
$this->sName, $this->iVendorId))
return false;
$this->sName = $sName;
}
if($this->sWebpage)
{
if (!query_parameters("UPDATE vendor SET vendorURL = '?' WHERE vendorId = '?'",
$this->sWebpage, $this->iVendorId))
return false;
$this->sWebpage = $sWebpage;
}
return true;
}
/**
* Remove the vendor from the database.
*/
function purge()
{
if(sizeof($this->aApplicationsIds)>0)
{
return FALSE;
} else
{
$sQuery = "DELETE FROM vendor
WHERE vendorId = '?'
LIMIT 1";
if(query_parameters($sQuery, $this->iVendorId))
{
return TRUE;
}
return FALSE;
}
return false;
}
/**
* Flag the vendor as deleted
*/
function delete()
{
if(sizeof($this->aApplicationsIds)>0)
{
return FALSE;
} else
{
$sQuery = "UPDATE vendor SET state = 'deleted'
WHERE vendorId = '?'
LIMIT 1";
if(query_parameters($sQuery, $this->iVendorId))
{
return TRUE;
}
return FALSE;
}
return false;
}
function checkOutputEditorInput($aClean)
{
if(!getInput('sVendorName', $aClean))
return '<li>You need to enter the developer\'s name</li>';
}
function outputEditor()
{
$oTable = new Table();
$oTable->SetWidth("100%");
$oTable->SetBorder(0);
$oTable->SetCellPadding(2);
$oTable->SetCellSpacing(0);
// name
$oTableRow = new TableRow();
$oTableCell = new TableCell("Developer name:");
$oTableCell->SetAlign("right");
$oTableCell->SetClass("color0");
$oTableCell->SetBold(true);
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell('<input type=text name="sVendorName" value="'.$this->sName.'" size="60">');
$oTableCell->SetClass("color0");
$oTableRow->AddCell($oTableCell);
$oTable->AddRow($oTableRow);
// Url
$oTableRow = new TableRow();
$oTableCell = new TableCell("Developer URL:");
$oTableCell->SetAlign("right");
$oTableCell->SetClass("color0");
$oTableCell->SetBold(true);
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell('<input type=text name="sVendorWebpage" value="'.$this->sWebpage.'" size="60">');
$oTableCell->SetClass("color0");
$oTableRow->AddCell($oTableCell);
$oTable->AddRow($oTableRow);
echo $oTable->GetString();
echo '<input type="hidden" name="iVendorId" value="'.$this->iVendorId.'">',"\n";
}
public static function objectGetSortableFields()
{
return array('vendorName');
}
public static function objectGetDefaultSort()
{
return 'vendorName';
}
function objectGetFilterInfo()
{
$oFilter = new FilterInterface();
$oFilter->AddFilterInfo('vendorName', 'Name', array(FILTER_CONTAINS, FILTER_STARTS_WITH, FILTER_ENDS_WITH), FILTER_VALUES_NORMAL);
return $oFilter;
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = 'vendorName', $bAscending = TRUE, $oFilter = null)
{
/* Not implemented */
if($sState == 'rejected')
return FALSE;
$sWhereFilter = $oFilter ? $oFilter->getWhereClause() : '';
$sOrder = $bAscending ? 'ASC' : 'DESC';
if($sWhereFilter)
$sWhereFilter = " AND $sWhereFilter";
if(!$iRows)
$iRows = Vendor::objectGetEntriesCount($sState, $oFilter);
$hResult = query_parameters("SELECT * FROM vendor WHERE state = '?' $sWhereFilter
ORDER BY $sOrderBy $sOrder LIMIT ?,?",
$sState, $iStart, $iRows);
if(!$hResult)
return FALSE;
return $hResult;
}
function objectGetHeader()
{
$oTableRow = new TableRowSortable();
$oTableRow->AddSortableTextCell('Name', 'vendorName');
$oTableCell = new TableCell('Applications');
$oTableRow->AddCell($oTableCell);
$oTableRow->AddTextCell("Website");
return $oTableRow;
}
// returns an OMTableRow instance
function objectGetTableRow()
{
$bDeleteLink = sizeof($this->aApplicationsIds) ? FALSE : TRUE;
// create the html table row
$oTableRow = new TableRow();
$oTableRow->AddTextCell($this->objectMakeLink());
$oTableCell = new TableCell(sizeof($this->aApplicationsIds));
$oTableRow->AddCell($oTableCell);
$oTableCell = new TableCell($this->sWebpage);
$oTableCell->SetCellLink($this->sWebpage);
$oTableRow->AddCell($oTableCell);
// create the object manager specific row
$oOMTableRow = new OMTableRow($oTableRow);
$oOMTableRow->SetHasDeleteLink($bDeleteLink);
return $oOMTableRow;
}
public function objectGetState()
{
return $this->sState;
}
function canEdit()
{
if($_SESSION['current']->hasPriv("admin"))
return TRUE;
else
return FALSE;
}
function mustBeQueued()
{
if($_SESSION['current']->hasPriv("admin"))
return FALSE;
else
return TRUE;
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return new mailOptions();
}
function objectGetChildren($bIncludeDeleted = false)
{
/* We don't have any */
return array();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
/* We don't send notification mails */
return array(null, null, null);
}
function objectGetSubmitterId()
{
/* We don't record the submitter id */
return NULL;
}
function getOutputEditorValues($aClean)
{
$this->sName = $aClean['sVendorName'];
$this->sWebpage = $aClean['sVendorWebpage'];
}
function display()
{
echo 'Developer name: '.$this->sName,"\n";
if($this->canEdit())
{
echo "[<a href=\"".$_SERVER['PHP_SELF']."?sClass=vendor&amp;sAction=edit&amp;".
"iId=$this->iVendorId&amp;sTitle=Edit%20Developer\">edit</a>]";
}
echo '<br>',"\n";
if ($this->sWebpage)
{
echo 'Developer URL: <a href="'.$this->sWebpage.'">'.
$this->sWebpage.'</a> <br>',"\n";
}
if($this->aApplicationsIds)
{
echo '<br>Applications by '.$this->sName.'<br><ol>',"\n";
foreach($this->aApplicationsIds as $iAppId)
{
$oApp = new Application($iAppId);
if($oApp->objectGetState() == 'accepted')
echo '<li>'.$oApp->objectMakeLink().'</li>',"\n";
}
echo '</ol>',"\n";
}
}
public function objectGetClassDisplayName()
{
return 'developer';
}
/* Make a URL for viewing the specified vendor */
function objectMakeUrl()
{
$oManager = new objectManager("vendor", "View Developer");
return $oManager->makeUrl("view", $this->iVendorId);
}
/* Make a HTML link for viewing the specified vendor */
function objectMakeLink()
{
return "<a href=\"".$this->objectMakeUrl()."\">$this->sName</a>";
}
function objectGetEntriesCount($sState, $oFilter = null)
{
/* Not implemented */
if($sState == 'rejected')
return FALSE;
$sWhereClause = $oFilter ? $oFilter->getWhereClause() : '';
if($sWhereClause)
$sWhereClause = " AND $sWhereClause";
$hResult = query_parameters("SELECT COUNT(vendorId) as count FROM vendor WHERE state = '?' $sWhereClause",
$sState);
if(!$hResult)
return FALSE;
if(!$oRow = query_fetch_object($hResult))
return FALSE;
return $oRow->count;
}
function allowAnonymousSubmissions()
{
return FALSE;
}
function objectMoveChildren($iNewId)
{
/* Keep track of how many children we have modified */
$iCount = 0;
foreach($this->aApplicationsIds as $iAppId)
{
$oApp = new application($iAppId);
$oApp->iVendorId = $iNewId;
if($oApp->update(TRUE))
$iCount++;
else
return FALSE;
}
return $iCount;
}
function objectGetId()
{
return $this->iVendorId;
}
function objectGetItemsPerPage($sState = 'accepted')
{
$aItemsPerPage = array(25, 50, 100, 200);
$iDefaultPerPage = 25;
return array($aItemsPerPage, $iDefaultPerPage);
}
function objectShowAddEntry()
{
return TRUE;
}
}
?>

1903
include/version.php Normal file

File diff suppressed because it is too large Load Diff

369
include/version_queue.php Normal file
View File

@@ -0,0 +1,369 @@
<?php
class version_queue
{
var $oTestDataQueue;
var $oVersion;
var $oDownloadUrl;
function version_queue($iVersionId = null, $oRow = null)
{
$this->oVersion = new version($iVersionId, $oRow);
$iTestingId = null;
$iDownloadUrlId = null;
if(!$iVersionId)
$iVersionId = $this->oVersion->iVersionId;
if($iVersionId)
{
$iTestingId = testData::getNewestTestIdFromVersionId($iVersionId, "pending");
/* This illustrates the importance of converting downloadurl completely
to the objectManager model. If we don't get a match searching for
a queued entry, try finding a rejected one. */
if(($hResult = appData::getData($iVersionId, "downloadurl",
TRUE, TRUE, FALSE)) ||
$hResult = appData::getData($iVersionId, "downloadurl",
TRUE, TRUE, TRUE))
{
if($oRow = query_fetch_object($hResult))
$iDownloadUrlId = $oRow->id;
}
}
$this->oTestDataQueue = new testData_queue($iTestingId);
$this->oDownloadUrl = new downloadurl($iDownloadUrlId);
if(!$this->oDownloadUrl->objectGetId() && $iVersionId)
$this->oDownloadUrl->objectSetParent($iVersionId);
}
function create()
{
global $aClean;
if(!$this->oVersion->create())
return FALSE;
$this->oTestDataQueue->oTestData->iVersionId = $this->oVersion->iVersionId;
$this->oTestDataQueue->create();
$this->oDownloadUrl->objectSetParent($this->oVersion->objectGetId());
$this->oDownloadUrl->create();
return TRUE;
}
function reQueue()
{
$this->oDownloadUrl->reQueue();
}
function reject()
{
$oApp = new application($this->oVersion->iAppId);
if($oApp->objectGetState() == 'accepted')
$this->oVersion->reject();
if($this->oDownloadUrl->iId)
$this->oDownloadUrl->reject();
}
function update()
{
$this->oVersion->update();
/* A downloadurl is optional and can thus be added later */
if($this->oDownloadUrl->objectGetId())
$this->oDownloadUrl->update();
else
$this->oDownloadUrl->create();
$this->oTestDataQueue->update();
}
function purge()
{
$bSuccess = TRUE;
if(!$this->oVersion->purge())
$bSuccess = FALSE;
if(!$this->oTestDataQueue->purge())
$bSuccess = FALSE;
if($this->oDownloadUrl->iId && !$this->oDownloadUrl->purge())
$bSuccess = FALSE;
return $bSuccess;
}
function delete()
{
$bSuccess = TRUE;
if(!$this->oVersion->delete())
$bSuccess = FALSE;
if(!$this->oTestDataQueue->delete())
$bSuccess = FALSE;
if($this->oDownloadUrl->iId && !$this->oDownloadUrl->delete())
$bSuccess = FALSE;
return $bSuccess;
}
function unQueue()
{
$this->oVersion->unQueue();
$this->oTestDataQueue->unQueue();
$this->oDownloadUrl->unQueue();
}
function objectGetSubmitterId()
{
return $this->oVersion->objectGetSubmitterId();
}
function objectGetChildren($bIncludeDeleted = false)
{
return $this->oVersion->objectGetChildren($bIncludeDeleted);
}
function objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction)
{
return $this->oVersion->objectGetMailOptions($sAction, $bMailSubmitter, $bParentAction);
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
return $this->oVersion->objectGetMail($sAction, $bMailSubmitter, $bParentAction);
}
function outputEditor()
{
global $aClean;
echo "<div class='default_container'>\n";
/* Display duplicate list if this is a an existing version */
if($this->oVersion->iVersionId)
$this->displayMoveTestTable();
$this->oVersion->outputEditor();
/* Allow the user to apply as maintainer if this is a new version.
If it is a new application as well, radio boxes will be displayed
by the application class instead. */
if(!$this->oVersion->iVersionId && $this->oVersion->iAppId &&
!$_SESSION['current']->isSuperMaintainer($this->oVersion->iAppId))
{
echo html_frame_start("Become a Maintainer or Monitor Changes", "90%");
echo "<div style='padding:5px;' class='color0'>\n";
$oTable = new Table();
if($this->oVersion->iMaintainerRequest == MAINTAINER_REQUEST)
$sRequestMaintainerChecked = 'checked="checked" ';
else
$sRequestMaintainerChecked = '';
if($this->oVersion->iMaintainerRequest == MONITOR_REQUEST)
$sRequestMonitorChecked = 'checked="checked"' ;
else
$sRequestMonitorChecked = '';
$oTableRow = new TableRow();
$oTableRow->AddTextCell('&nbsp;');
$oTableRow->AddTextCell("<input type=\"radio\" $sRequestMaintainerChecked".
"name=\"iMaintainerRequest\" value=\"".MAINTAINER_REQUEST."\"> ".
"Request being a maintainer for this version, allowing you to edit it later");
$oTable->AddRow($oTableRow);
$oTableRow = new TableRow();
$oTableRow->AddTextCell('&nbsp;');
$oTableRow->AddTextCell("<input type=\"radio\" $sRequestMonitorChecked".
"name=\"iMaintainerRequest\" value=\"".MONITOR_REQUEST."\"> ".
"Monitor changes to this version, also after it has been accepted");
$oTable->AddRow($oTableRow);
$oTableRow = new TableRow();
$oTableRow->AddTextCell('&nbsp;');
$oTableRow->AddTextCell('<input type="radio" name="iMaintainerRequest" value="0"> '.
'None of the above');
$oTable->AddRow($oTableRow);
echo $oTable->GetString();
echo "</div\n";
echo html_frame_end();
}
echo $this->oDownloadUrl->outputEditorSingle($this->oVersion->iVersionId,
$aClean);
$this->oTestDataQueue->outputEditor();
echo "</div>\n";
}
function getOutputEditorValues($aClean)
{
$this->oVersion->iAppId = $aClean['iAppId'];
$this->oVersion->getOutputEditorValues($aClean);
$this->oDownloadUrl->getOutputEditorValues($aClean);
$this->oTestDataQueue->getOutputEditorValues($aClean);
}
function checkOutputEditorInput($aClean)
{
$sErrors = $this->oVersion->checkOutputEditorInput($aClean);
$sErrors .= $this->oTestDataQueue->checkOutputEditorInput($aClean);
return $sErrors;
}
function objectGetState()
{
return $this->oVersion->objectGetState();
}
function canEdit()
{
return $this->oVersion->canEdit();
}
function mustBeQueued()
{
return $this->oVersion->mustBeQueued();
}
function objectDisplayAddItemHelp()
{
/* $this->oVersion->displayAddItemHelp(); */
}
function objectGetItemsPerPage($sState = 'accepted')
{
return $this->oVersion->objectGetItemsPerPage($sState);
}
function objectGetEntriesCount($sState)
{
return $this->oVersion->objectGetEntriesCount($sState);
}
public static function objectGetDefaultSort()
{
return version::objectGetDefaultSort();
}
function objectGetEntries($sState, $iRows = 0, $iStart = 0, $sOrderBy = "versionId", $bAscending = true)
{
return $this->oVersion->objectGetEntries($sState, $iRows, $iStart,
$sOrderBy, $bAscending);
}
function objectGetHeader()
{
return $this->oVersion->objectGetHeader();
}
function objectGetTableRow()
{
return $this->oVersion->objectGetTableRow();
}
public function objectShowPreview()
{
return $this->oVersion->objectShowPreview();
}
function display()
{
/* Cache the test result object as it's not in the DB */
$this->oVersion->aTestResults[] = $this->oTestDataQueue->oTestData;
$this->oVersion->display();
}
function objectMakeUrl()
{
return $this->oVersion->objectMakeUrl();
}
function objectMakeLink()
{
return $this->oVersion->objectMakeLink();
}
function displayMoveTestTable()
{
$oApp = new application($this->oVersion->iAppId);
echo html_frame_start("Move test to version","90%","",0);
echo "<table width=\"100%\" border=\"0\" cellpadding=\"3\" ".
"cellspacing=\"1\">\n\n";
echo html_tr(array(
array("Version", 'width="80"'),
"Description",
array("Rating", 'width="80"'),
array("Wine version", 'width="80"'),
array("Comments", 'width="40"'),
array("Move test results", 'width="80"')
),
"color4");
$i = 0;
foreach($oApp->aVersionsIds as $iVersionId)
{
$oVersion = new Version($iVersionId);
if ($oVersion->objectGetState() == 'accepted')
{
//display row
echo html_tr(array(
$oVersion->objectMakeLink(),
util_trim_description($oVersion->sDescription),
array($oVersion->sTestedRating, 'align="center"'),
array($oVersion->sTestedRelease, 'align="center"'),
array(Comment::get_comment_count_for_versionid(
$oVersion->iVersionId), 'align="center"'),
html_ahref("Move here",
"objectManager.php?sClass=version_queue&amp;bIsQueue=true&amp;".
"sAction=moveChildren&amp;iId=".
$this->oVersion->iVersionId."&amp;iNewId=".
$oVersion->iVersionId."&amp;sTitle=Version+Queue"),
),
($i % 2) ? "color0" : "color1");
$i++;
}
}
echo "</table>\n";
echo html_frame_end("&nbsp;");
}
function objectDisplayQueueProcessingHelp()
{
version::objectDisplayQueueProcessingHelp();
}
function objectMoveChildren($iNewId)
{
return $this->oVersion->objectMoveChildren($iNewId);
}
function allowAnonymousSubmissions()
{
return version::allowAnonymousSubmissions();
}
function objectAllowPurgingRejected()
{
return $this->oVersion->objectAllowPurgingRejected();
}
public function objectGetSubmitTime()
{
return $this->oVersion->objectGetSubmitTime();
}
function objectGetId()
{
return $this->oVersion->objectGetId();
}
}
?>

505
include/vote.php Normal file
View File

@@ -0,0 +1,505 @@
<?php
require_once(BASE."include/util.php");
/* max votes per user */
define('MAX_VOTES',3);
class vote
{
public $iUserId;
public $iVoteId;
public $iSlotIndex;
public $iVersionId;
public function vote($iVoteId = null, $oRow = null)
{
if(!$iVoteId && !$oRow) /* Nothing to do */
return;
if(!$oRow)
{
$hResult = query_parameters("SELECT * FROM appVotes WHERE id = '?'", $iVoteId);
$oRow = mysql_fetch_object($hResult);
}
if($oRow)
{
$this->iUserId = $oRow->userId;
$this->iVoteId = $oRow->id;
$this->iSlotIndex = $oRow->slot;
$this->iVersionId = $oRow->versionId;
}
}
public function update()
{
/* Check for valid vote slot index */
if($this->iSlotIndex < 1 || $this->iSlotIndex > MAX_VOTES)
return;
/* Avoid pointless votes */
if(!$this->iVersionId)
return;
if(!$this->iVoteId)
{
$hResult = query_parameters("INSERT INTO appVotes (versionId,userId,slot) VALUES('?','?','?')",
$this->iVersionId, $_SESSION['current']->iUserId, $this->iSlotIndex);
} else
{
$hResult = query_parameters("UPDATE appVotes SET versionId = '?' WHERE id = '?'", $this->iVersionId, $this->iVoteId);
}
if(!$hResult)
return FALSE;
return TRUE;
}
public function delete()
{
/* A vote needs to have a versionId, so if it doesn't that means it is not in the
database or it was not selected in the vote editor */
if(!$this->iVersionId)
return TRUE;
$hResult = query_parameters("DELETE FROM appVotes WHERE id = '?'", $this->iVoteId);
if(!$hResult)
return FALSE;
return TRUE;
}
public function getVotesForVersion($iVersionId)
{
$aRet = array();
$hResult = query_parameters("SELECT * FROM appVotes WHERE versionId = '?'",
$iVersionId);
if(!$hResult)
return $aRet;
while($oRow = mysql_fetch_object($hResult))
$aRet[] = new vote(null, $oRow);
return $aRet;
}
public function objectGetId()
{
return $this->iVoteId;
}
public function objectGetSubmitterId()
{
return $this->iUserId;
}
public function objectGetParent($sClass = '')
{
return new version($this->iVersionId);
}
public function objectSetParent($iNewId, $sClass = '')
{
$this->iVersionId = $iNewId;
}
public function canEdit()
{
if($_SESSION['current']->iUserId == $this->iUserId)
return true;
$oVersion = new version($this->iVersionId);
return $oVersion->canEdit();
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
return array(null, null, null); /* No mail */
}
public static function objectGetMailOptions($sAction, $bMailSubmitter,
$bParentAction)
{
return new mailOptions();
}
}
class voteManager
{
private $iUserId;
private $aVotes;
public function voteManager($iUserId = null, $oRow = null)
{
$this->iUserId = $iUserId;
}
public function objectGetCustomVars($sAction)
{
switch($sAction)
{
case "edit":
return array("iVersionId");
break;
default:
return null;
}
}
public function outputEditor($aClean = null)
{
echo "The following shows your current votes. Check the boxes next to the apps you wish to replace with a vote for ".version::fullNameLink($aClean['iVersionId'])." or delete.";
$oTable = new table();
$this->aVotes = $this->getVotes();
for($i = 0; $i < MAX_VOTES; $i++)
{
$sVersionText = $this->aVotes[$i]->iVersionId ? version::fullNameLink($this->aVotes[$i]->iVersionId) : "No app selected";
$oTableRow = new tableRow();
$oTableRow->addTextCell('<input type="checkbox" name="iSlot'.$i.'" value="'.$aClean['iVersionId'].'">');
$oTableRow->addTextCell($sVersionText);
$oTable->addRow($oTableRow);
}
echo $oTable->getString();
}
public function canEdit()
{
if($_SESSION['current']->iUserId == $this->iUserId)
return TRUE;
return FALSE;
}
function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
return array(null, null, null); /* No mail */
}
public function mustBeQueued()
{
return FALSE;
}
public function objectGetEntries($bQueued, $bRejected)
{
return query_parameters("SELECT * FROM appVotes");
}
public function objectGetId()
{
return $this->iUserId;
}
public function create()
{
return TRUE;
}
function purge()
{
return $this->delete();
}
public function delete()
{
$bSuccess = TRUE;
if(!is_array($this->aVotes))
$this->aVotes = $this->getVotes();
foreach($this->aVotes as $oVote)
{
if(!$oVote->delete())
$bSuccess = FALSE;
}
return $bSuccess;
}
public function update()
{
foreach($this->aVotes as $oVote)
$oVote->update();
}
public function getOutputEditorValues($aClean)
{
$this->aVotes = $this->getVotes();
for($i = 0; $i < MAX_VOTES; $i++)
$this->aVotes[$i]->iVersionId = $aClean["iSlot$i"];
}
public function objectGetEntriesCount()
{
$hResult = query_parameters("SELECT COUNT(id) as count FROM appVotes");
if(!$hResult)
return FALSE;
if(!($oRow = mysql_fetch_object($hResult)))
return FALSE;
return $oRow->count;
}
public function objectGetSubmitterId()
{
return $this->iUserId;
}
public function getVotes()
{
$aVotes = array();
$hResult = query_parameters("SELECT * FROM appVotes WHERE userId = '?' ORDER BY slot", $this->iUserId);
if(!$hResult)
return $aVotes;
for($i = 0; $i < MAX_VOTES; $i++)
$aVotes[$i] = null;
while($oRow = mysql_fetch_object($hResult))
$aVotes[$oRow->slot-1] = new vote(null, $oRow);
for($i = 0; $i < MAX_VOTES; $i++)
{
if(!$aVotes[$i])
{
$aVotes[$i] = new vote();
$aVotes[$i]->iSlotIndex = $i+1;
}
}
return $aVotes;
}
}
/**
* used by admins to check whether votes for a version are legit
*/
class voteInspector
{
private $iVersionId;
private $aDeleteVoters;
function voteInspector($iVersionId = null)
{
if(is_numeric($iVersionId))
$this->iVersionId = $iVersionId;
$this->aDeleteVoters = array();
}
public function objectGetId()
{
return $this->iVersionId;
}
public function objectGetState()
{
return 'accepted';
}
public function canEdit()
{
return $_SESSION['current']->hasPriv('admin');
}
public function objectGetSubmitterId()
{
return -1;
}
public function getVotes()
{
return query_parameters("SELECT userId, COUNT(userId) as count FROM appVotes WHERE
versionId = '?'
GROUP BY userId", $this->iVersionId);
}
public function getVoteCount()
{
return vote_count_version_total($this->iVersionId);
}
public function getVoterCount()
{
return mysql_num_rows($this->getVotes());
}
public function outputEditor()
{
$oVersion = new version($this->iVersionId);
echo 'Inspecting votes for ' . version::fullNameLink($this->iVersionId).'<br />';
echo 'Total votes: '.$this->getVoteCount().'<br />';
echo 'To delete bogus user accounts, select them and press the Delete button below.<br /><br />';
$hResult = $this->getVotes();
if(!$hResult)
{
echo 'Failed to get list of votes';
return;
}
if(mysql_num_rows($hResult) == 0)
{
echo 'There are no votes for this version';
return;
}
$oTable = new Table();
$oTable->setCellPadding(3);
$oTableRow = new TableRow();
$oTableRow->setClass('color4');
$oTableRow->AddTextCell('Delete account');
$oTableRow->AddTextCell('User');
$oTableRow->AddTextCell('ID');
$oTableRow->AddTextCell('E-mail');
$oTableRow->AddTextCell('Created');
$oTableRow->AddTextCell('Votes');
$oTableRow->AddTextCell('Privileges');
$oTableRow->AddTextCell('Test data');
$oTableRow->AddTextcell('Comments');
$oTable->AddRow($oTableRow);
for($i = 0; $oRow = mysql_fetch_object($hResult); $i++)
{
$oVoter = new user($oRow->userId);
$oTableRow = new TableRow();
$oTableRow->setClass(($i % 2) ? 'color0' : 'color1');
if($oVoter->hasPriv('admin'))
$shDelete = '';
else
$shDelete = "<input type=\"checkbox\" name=\"iDelSlot$i\" value=\"{$oVoter->iUserId}\" />";
$oTableRow->AddTextCell($shDelete);
$oTableRow->AddTextCell($oVoter->objectMakeLink());
$oTableRow->AddTextCell($oVoter->iUserId);
$oTableRow->AddTextCell($oVoter->sEmail);
$oTableRow->AddTextCell($oVoter->sDateCreated);
$oTableRow->AddTextCell($oRow->count);
$sPrivs = '';
if($oVoter->hasPriv('admin'))
$sPrivs .= 'Admin<br />';
if($oVoter->isMaintainer($this->iVersionId))
$sPrivs .= 'Maintainer of this version<br />';
if($oVoter->isMaintainer())
{
$oM = new objectManager('maintainerView', 'View maintainership info');
$sPrivs .= '<a href="'.$oM->makeUrl('view',$oVoter->iUserId).'">Maintainer (other entries)</a><br />';
}
$oTableRow->AddTextCell($sPrivs);
$hSubResult = query_parameters("SELECT COUNT(testingId) AS count FROM testResults WHERE submitterId = '?' AND state != 'deleted'", $oVoter->iUserId);
if($hSubResult && ($oSubRow = mysql_fetch_object($hSubResult)))
$sSubmitted = $oSubRow->count;
else
$sSubmitted = 'DB failure';
$oTableRow->AddTextCell($sSubmitted);
$hSubResult = query_parameters("SELECT COUNT(commentId) as count FROM appComments WHERE userId = '?'", $oVoter->iUserId);
if($hSubResult && ($oSubRow = mysql_fetch_object($hSubResult)))
$sSubmitted = $oSubRow->count;
else
$sSubmitted = 'DB failure';
$oTableRow->AddTextCell($sSubmitted);
$oTable->AddRow($oTableRow);
}
echo $oTable->getString();
}
public function getOutputEditorValues($aValues)
{
$iVoters = $this->getVoterCount();
$this->aDeleteVoters = array();
for($i = 0; $i < $iVoters; $i++)
{
if(($iVoterId = getInput("iDelSlot$i", $aValues)))
$this->aDeleteVoters[] = new user($iVoterId);
}
}
public function create()
{
return true;
}
public function update()
{
return true;
}
public function objectGetMail($sAction, $bMailSubmitter, $bParentAction)
{
$sSubject = '';
$sMsg = '';
$aMailTo = null;
return array($sSubject, $sMsg, $aMailTo);
}
public function delete()
{
$bSuccess = true;
foreach($this->aDeleteVoters as $oVoter)
{
if(!$oVoter->delete())
$bSuccess = false;
}
return $bSuccess;
}
}
/**
* count the number of votes for appId by userId
*/
function vote_count($iVersionId, $iUserId = null)
{
if(!$iUserId)
{
if($_SESSION['current']->isLoggedIn())
$iUserId = $_SESSION['current']->iUserId;
else
return 0;
}
$hResult = query_parameters("SELECT * FROM appVotes WHERE versionId = '?' AND userId = '?'",
$iVersionId, $iUserId);
return query_num_rows($hResult);
}
/*
* total votes for versionId
*/
function vote_count_version_total($iVersionId)
{
$hResult = query_parameters("SELECT * FROM appVotes WHERE versionId = '?'",
$iVersionId);
return query_num_rows($hResult);
}
?>