source: trunk/website/scripts/BuildServer.php @ 2391

Revision 2391, 3.7 KB checked in by lowjoel, 3 years ago (diff)

Added database support for build slave information.

Line 
1<?php
2//HTTP Digest authentication code, modified from http://php.net/manual/en/features.http-auth.php
3define('HTTP_DIGEST_REALM', 'Build Server');
4
5//Function to challenge the user
6function http_digest_challenge() {
7    header('HTTP/1.1 401 Unauthorized');
8    header(sprintf('WWW-Authenticate: Digest realm="%s",qop="auth",nonce="%s",opaque="%s"',
9        HTTP_DIGEST_REALM, uniqid(), md5(HTTP_DIGEST_REALM)));
10    die('Authorisation required.');
11}
12
13//Function to parse the HTTP auth header
14function http_digest_parse($txt) {
15    // protect against missing data
16    $needed_parts = array('nonce' => 1,
17        'nc' => 1,
18        'cnonce' => 1,
19        'qop' => 1,
20        'username' => 1,
21        'uri' => 1,
22        'response' => 1
23    );
24    $data = array();
25
26    preg_match_all('@(\w+)=(?:(?:\'([^\']+)\'|"([^"]+)")|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);
27
28    foreach ($matches as $m)
29    {
30        $data[$m[1]] = $m[2] ? $m[2] : ($m[3] ? $m[3] : $m[4]);
31        unset($needed_parts[$m[1]]);
32    }
33
34    return $needed_parts ? false : $data;
35}
36
37//Challenge the client if we did not receive the digest
38if (empty($_SERVER['PHP_AUTH_DIGEST']))
39    http_digest_challenge();
40
41//Analyze the PHP_AUTH_DIGEST variable
42$credentials = http_digest_parse($_SERVER['PHP_AUTH_DIGEST']);
43if (!$credentials)
44    http_digest_challenge();
45
46//Does the user exist?
47require_once('Credentials.php');
48require_once('Database.php');
49$database = new Database();
50$count = $database->query(sprintf('SELECT COUNT(*) FROM build_slaves WHERE Username=%s',
51    $database->quote($credentials['username'])))->fetch();
52$count = $count[0];
53if (!$count)
54    http_digest_challenge();
55
56//Check the response for the password.
57$password = $database->query(sprintf('SELECT Password FROM build_slaves WHERE Username=%s',
58    $database->quote($credentials['username'])))->fetch();
59$password = $password['Password'];
60$A1 = md5($credentials['username'] . ':' . HTTP_DIGEST_REALM . ':' . $password);
61$A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $credentials['uri']);
62$valid_response = md5($A1 . ':' . $credentials['nonce'] . ':' . $credentials['nc'] . ':' .
63        $credentials['cnonce'] . ':' . $credentials['qop'] . ':' . $A2);
64if ($credentials['response'] != $valid_response)
65    http_digest_challenge();
66
67require_once('Build.php');
68require_once('BuildUtil.php');
69require_once('BuildBranch.php');
70
71try
72{
73    //Check that we have all the necessary information
74    $branches = BuildBranch::Get();
75    if (!is_numeric($_GET['revision']) || !is_numeric($_GET['filesize']) || empty($_GET['url']) || empty($_GET['branch']))
76        throw new Exception('Invalid build information provided.');
77    if (!array_key_exists($_GET['branch'], $branches))
78        throw new Exception('The branch ' . $_GET['branch'] . ' does not exist.');
79
80    //Get the branch the notification is for
81    $branch = $branches[$_GET['branch']];
82
83    //Insert the build to the database.
84    ob_start();
85    printf('Inserting build into database... ');
86    Build::CreateBuild($branch->ID, intval($_GET['revision']), intval($_GET['filesize']), $_GET['url']);
87    printf("Inserted.\n");
88
89    //Remove old builds
90    printf('Removing old builds from database...' . "\n");
91
92    $pdo = new Database();
93    $statement = $pdo->prepare('UPDATE downloads SET Superseded=1 WHERE DownloadID=?');
94
95    $builds = Build::GetActive($branch->ID);
96    for ($i = 0, $j = count($builds) - 3; $i < $j; ++$i)
97    {
98        printf("\n\t" . 'Removing build %s' . "\n\t\t", $builds[$i]->Name);
99
100        //Delete the copy on the SourceForge web server.
101        Delete(SHELL_WEB_ROOT . parse_url($builds[$i]->Link, PHP_URL_PATH), $sftp_username,
102            $sftp_password);
103
104        //Remove from the database
105        $statement->execute(array($builds[$i]->ID));
106    }
107   
108    header('content-type: text/plain');
109    ob_end_flush();
110}
111catch (Exception $e)
112{
113    ob_end_clean();
114    header('500 Internal Server Error');
115    echo $e->getMessage();
116}
117?>
Note: See TracBrowser for help on using the repository browser.