source: trunk/website/scripts/downloads.php @ 1312

Revision 1312, 6.8 KB checked in by lowjoel, 4 years ago (diff)

Factorise out the build database insertion code to a separate function.

Line 
1<?php
2require('database.php');
3
4class Download
5{
6    protected $ID;
7
8    public function Download($downloadID)
9    {
10        $query = mysql_query(sprintf('SELECT COUNT(DownloadID) FROM downloads WHERE DownloadID=%d',
11            intval($downloadID)));
12        if (($row = mysql_fetch_row($query)) === false || $row[0] == 0)
13            throw new Exception(sprintf('Could not find download %d', $downloadID));
14
15        $this->ID = $downloadID;
16    }
17   
18    public function InitiateDownload()
19    {
20        //Register the download
21        mysql_query(sprintf('INSERT INTO download_log (DownloadID) VALUES (%d)', $this->ID));
22       
23        if (preg_match('/http(s{0,1}):\/\/(.*)/', $this->Link))
24            header('location: ' . $this->Link);
25        else if (substr($this->Link, 0, 1) == '?')
26            Download::DownloadFile(substr($this->Link, 1));
27        throw new Exception('Unknown download link');
28    }
29   
30    public function __get($varName)
31    {
32        $sql = sprintf('SELECT %%s FROM downloads WHERE DownloadID=%d', $this->ID);
33        switch ($varName)
34        {
35            case 'ID':
36                return $this->ID;
37
38            case 'Downloads':
39                $sql = sprintf('SELECT Downloads FROM download_statistics WHERE DownloadID=%d', $this->ID);
40                break;
41
42            case 'Name':
43            case 'Released':
44            case 'Superseded':
45            case 'Link':
46                $sql = sprintf($sql, $varName);
47                break;
48        }
49       
50        if (empty($sql))
51            return null;
52       
53        $query = mysql_query($sql);
54        $row = $query ? mysql_fetch_row($query) : null;
55        $result = $row ? $row[0] : null;
56       
57        if ($result !== null)
58            switch ($varName)
59            {
60                case 'Downloads':
61                    $result = intval($result);
62                    break;
63                case 'Released':
64                    $result = MySqlToPhpTimestamp($result);
65                    break;
66            }
67       
68        return $result;
69    }
70
71    public function __set($varName, $value)
72    {
73        $sql = sprintf('UPDATE downloads SET %%s=%%s WHERE DownloadID=%d', $this->ID);
74        switch ($varName)
75        {
76            case 'Superseded':
77                $sql = sprintf($sql, $varName, intval($value));
78                break;
79            default:
80                return;
81        }
82       
83        if (empty($sql))
84            return;
85        mysql_query($sql);
86    }
87   
88    private static function DownloadFile($path, $visibleName = null)
89    {
90        $downloadFolder = dirname(__FILE__) . '/../downloads/';
91        $visibleName = $visibleName == null ? basename($path) : $visibleName;
92
93        header('Content-Type: application/octet-stream');
94        header('Content-Length: ' . filesize($downloadFolder . $path));
95        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)
96        {
97            //IE browser
98            header('Content-Disposition: inline; filename="' . $visibleName . '"');
99            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
100            header('Pragma: public');
101        }
102        else
103        {
104            header('Content-Disposition: attachment; filename="' . $visibleName . '"');
105            header('Pragma: no-cache');
106        }
107   
108        echo file_get_contents($downloadFolder . $path);
109    }
110};
111
112class Build extends Download
113{
114    public function Build($path, $revision)
115    {
116        $query = mysql_query(sprintf('SELECT downloads.DownloadID FROM downloads INNER JOIN builds ON
117            downloads.DownloadID=builds.DownloadID WHERE
118                builds.Path=\'%s\' AND builds.Revision=%d',
119            mysql_real_escape_string($path), intval($revision)));
120       
121        //See if the build already has a database entry
122        if (($row = mysql_fetch_row($query)) === false || !$row[0])
123        {
124            $this->ID = Build::InsertBuild($path, $revision);
125        }
126        else
127        {
128            $this->ID = intval($row[0]);
129
130            //Check that the folder has not been removed. This may indicate supersedence.
131            if (!file_exists(Build::GetPath($this->Path, $this->Revision)))
132                $this->Superseded = 1;
133        }
134    }
135   
136    public static function Get()
137    {
138        $result = array();
139        $builds = array('Eraser5' => 'Eraser 5', 'Eraser6' => 'Eraser 6');
140        foreach ($builds as $path => $buildName)
141        {
142            $revisions = opendir(Build::GetPath($path));
143            $result[$buildName] = array();
144
145            while (($revision = readdir($revisions)) !== false)
146            {
147                if (!sprintf('downloads/builds/%s/%s', $path, $revision) || $revision == '.' || $revision == '..')
148                    continue;
149               
150                try
151                {
152                    $result[$buildName][] = new Build($path, intval(substr($revision, 1)));
153                }
154                catch (Exception $e)
155                {
156                }
157            }
158        }
159       
160        return $result;
161    }
162   
163    public static function GetBuildFromID($downloadID)
164    {
165        $query = mysql_query(sprintf('SELECT * FROM builds WHERE DownloadID=%d', intval($downloadID)));
166        if (($row = mysql_fetch_array($query)) === false || !$row[0])
167            return null;
168
169        return intval($row[0]) ? new Build($row['Path'], $row['Revision']) : null;
170    }
171   
172    public function __get($varName)
173    {
174        $sql = sprintf('SELECT %%s FROM builds WHERE DownloadID=%d', $this->ID);
175        switch ($varName)
176        {
177            case 'Revision':
178            case 'Path':
179                $sql = sprintf($sql, $varName);
180                break;
181
182            default:
183                return parent::__get($varName);
184        }
185       
186        $query = mysql_query($sql);
187        $row = $query ? mysql_fetch_row($query) : null;
188       
189        return $row ? $row[0] : null;
190    }
191   
192    private static function InsertBuild($path, $revision)
193    {
194        //It doesn't. Find the binary that users will get to download.
195        $directory = opendir(Build::GetPath($path, $revision));
196        $installer = null;
197        $installerFilesize = 0;
198        while (($file = readdir($directory)) !== false)
199        {
200            $filePath = Build::GetPath($path, $revision) . '/' . $file;
201            if (is_file($filePath))
202            {
203                $pathInfo = pathinfo($filePath);
204                if ($pathInfo['extension'] == 'exe')
205                {
206                    $installer = sprintf('builds/%s/r%s/%s', $path, $revision, $file);
207                    $installerFilesize = filesize($filePath);
208                    break;
209                }
210            }
211        }
212       
213        if (empty($installer) || $installerFilesize == 0)
214        {
215            //It is a build in progress, don't create anything.
216            throw new Exception(sprintf('Build %s r%d is incomplete.', $path, $revision));
217        }
218       
219        mysql_query('START TRANSACTION');
220        mysql_query(sprintf('INSERT INTO downloads (Name, Released, `Type`, Version, PublisherID, Architecture, Filesize, Link)
221                VALUES (
222                    \'%1$s r%2$d\', \'%4$s\' , \'build\', \'r%2$d\', 1, \'any\', %3$d, \'?%5$s\'
223                )',
224            mysql_real_escape_string($path), intval($revision), $installerFilesize,
225            PhpToMySqlTimestamp(filemtime(Build::GetPath($path, $revision))),
226            mysql_real_escape_string($installer)))
227                or die(mysql_error());
228        mysql_query(sprintf('INSERT INTO builds (DownloadID, Path, Revision)
229                VALUES (
230                    LAST_INSERT_ID(), \'%1s\', %2$d
231                )',
232            mysql_real_escape_string($path), intval($revision))) or die(mysql_error());
233
234        if (!mysql_affected_rows())
235            throw new Exception(sprintf('Could not create new build %s r%d. MySQL Error: %s', $path, $revision, mysql_error()));
236        $buildId = mysql_insert_id();
237       
238        mysql_query('COMMIT');
239        return $buildId;
240    }
241   
242    private static function GetPath($path, $revision = null)
243    {
244        return sprintf('%s/../downloads/builds/%s%s', dirname(__FILE__), $path,
245            $revision === null ? '' : sprintf('/r%s', $revision));
246    }
247};
248?>
Note: See TracBrowser for help on using the repository browser.