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

Revision 2386, 3.3 KB checked in by lowjoel, 3 years ago (diff)

Factor the utility functions used by the Build slaves to a separate BuildUtil? file which is referenced by both the build server and build client scripts.

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    exit;
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//user => password
38$users = array('admin' => 'mypass', 'guest' => 'guest');
39
40//Challenge the client if we did not receive the digest
41if (empty($_SERVER['PHP_AUTH_DIGEST']))
42    http_digest_challenge();
43
44//Analyze the PHP_AUTH_DIGEST variable
45$credentials = http_digest_parse($_SERVER['PHP_AUTH_DIGEST']);
46if (!$credentials || !isset($users[$credentials['username']]))
47    http_digest_challenge();
48
49//Check the response
50$A1 = md5($credentials['username'] . ':' . HTTP_DIGEST_REALM . ':' . $users[$credentials['username']]);
51$A2 = md5($_SERVER['REQUEST_METHOD'] . ':' . $credentials['uri']);
52$valid_response = md5($A1 . ':' . $credentials['nonce'] . ':' . $credentials['nc'] . ':' .
53        $credentials['cnonce'] . ':' . $credentials['qop'] . ':' . $A2);
54if ($credentials['response'] != $valid_response)
55    http_digest_challenge();
56
57require('Build.php');
58require('BuildUtil.php');
59require('Credentials.php');
60require('Database.php');
61
62try
63{
64    //Check that we have all the necessary information
65    $branches = BuildBranch::Get();
66    if (!array_key_exists($_GET['branch'], $branches))
67        throw new Exception('The branch ' . $_GET['branch'] . ' does not exist.');
68    if (!is_numeric($_GET['revision']) || !is_numeric($_GET['filesize']) || empty($_GET['url']))
69        throw new Exception('Invalid build information provided.');
70
71    //Get the branch the notification is for
72    define('HTTP_WEB_ROOT', 'http://eraser.sourceforge.net');
73    $branch = $branches[$_GET['branch']];
74
75    //Insert the build to the database.
76    printf('Inserting build into database... ');
77    Build::CreateBuild($branch->ID, intval($_GET['revision']), intval($_GET['filesize']), $_GET['url']);
78    printf("Inserted.\n");
79
80    //Remove old builds
81    printf('Removing old builds from database...' . "\n");
82
83    $pdo = new Database();
84    $statement = $pdo->prepare('UPDATE downloads SET Superseded=1 WHERE DownloadID=?');
85
86    $builds = Build::GetActive($branch->ID);
87    for ($i = 0, $j = count($builds) - 3; $i < $j; ++$i)
88    {
89        printf("\n\t" . 'Removing build %s' . "\n\t\t", $builds[$i]->Name);
90
91        //Delete the copy on the SourceForge web server.
92        Delete(SHELL_WEB_ROOT . parse_url($builds[$i]->Link, PHP_URL_PATH), $sftp_username,
93            $sftp_password);
94
95        //Remove from the database
96        $statement->execute(array($builds[$i]->ID));
97    }
98}
99catch (Exception $e)
100{
101    echo $e->getMessage();
102    exit(1);
103}
104?>
Note: See TracBrowser for help on using the repository browser.