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

Revision 1762, 8.9 KB checked in by lowjoel, 4 years ago (diff)

Do not unset and reset the superseded field of the table as that re-enables downloads which have been superseded in the database only.

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        {
25            header('location: ' . $this->Link);
26        }
27        else if (substr($this->Link, 0, 1) == '?')
28        {
29            //Get a name to call the file.
30            $pathInfo = pathinfo(substr($this->Link, 1));
31            Download::DownloadFile(substr($this->Link, 1),
32                sprintf('%s.%s', $this->Name, $pathInfo['extension']));
33        }
34        else
35        {
36            throw new Exception('Unknown download link');
37        }
38    }
39   
40    public function __get($varName)
41    {
42        $sql = sprintf('SELECT %%s FROM downloads WHERE DownloadID=%d', $this->ID);
43        switch ($varName)
44        {
45            case 'ID':
46                return $this->ID;
47
48            case 'Downloads':
49                $sql = sprintf('SELECT Downloads FROM download_statistics WHERE DownloadID=%d', $this->ID);
50                break;
51
52            case 'Name':
53            case 'Released':
54            case 'Superseded':
55            case 'Link':
56                $sql = sprintf($sql, $varName);
57                break;
58        }
59       
60        if (empty($sql))
61            return null;
62       
63        $query = mysql_query($sql);
64        $row = $query ? mysql_fetch_row($query) : null;
65        $result = $row ? $row[0] : null;
66       
67        if ($result !== null)
68            switch ($varName)
69            {
70                case 'Downloads':
71                    $result = intval($result);
72                    break;
73                case 'Released':
74                    $result = MySqlToPhpTimestamp($result);
75                    break;
76            }
77       
78        return $result;
79    }
80
81    public function __set($varName, $value)
82    {
83        $sql = sprintf('UPDATE downloads SET %%s=%%s WHERE DownloadID=%d', $this->ID);
84        switch ($varName)
85        {
86            case 'Superseded':
87                $sql = sprintf($sql, $varName, intval($value));
88                break;
89            default:
90                return;
91        }
92       
93        if (empty($sql))
94            return;
95        mysql_query($sql);
96    }
97   
98    private static function DownloadFile($path, $visibleName = null)
99    {
100        $downloadFolder = dirname(__FILE__) . '/../downloads/';
101        $visibleName = $visibleName == null ? basename($path) : $visibleName;
102
103        header('Content-Type: application/octet-stream');
104        header('Content-Length: ' . filesize($downloadFolder . $path));
105        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE') !== false)
106        {
107            //IE browser
108            header('Content-Disposition: inline; filename="' . $visibleName . '"');
109            header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
110            header('Pragma: public');
111        }
112        else
113        {
114            header('Content-Disposition: attachment; filename="' . $visibleName . '"');
115            header('Pragma: no-cache');
116        }
117
118        readfile($downloadFolder . $path);
119    }
120};
121
122class Build extends Download
123{
124    public function Build($branch, $revision)
125    {
126        $query = mysql_query(sprintf('SELECT DownloadID FROM builds WHERE
127                Branch=\'%s\' AND Revision=%d',
128            mysql_real_escape_string($branch), intval($revision)));
129       
130        //See if the build already has a database entry
131        if (($row = mysql_fetch_row($query)) === false || !$row[0])
132        {
133            throw new Exception('Build does not exist');
134        }
135        else
136        {
137            $this->ID = intval($row[0]);
138
139            //Check that the folder has not been removed. This may indicate supersedence.
140            $downloadFolder = dirname(__FILE__) . '/../downloads/';
141            if (!file_exists($downloadFolder . substr($this->Link, 1)))
142                $this->Superseded = 1;
143        }
144    }
145   
146    public static function Get()
147    {
148        $result = array();
149        $builds = array('Eraser5' => 'Eraser 5', 'Eraser6' => 'Eraser 6.0', 'Eraser6.2' => 'Eraser 6.2');
150        $versions = array('Eraser5' => '5.8.9', 'Eraser6' => '6.0.6', 'Eraser6.2' => '6.1.0');
151        foreach ($builds as $branchName => $buildName)
152        {
153            $revisions = opendir(Build::GetPath($branchName));
154            $result[$buildName] = array();
155
156            while (($revision = readdir($revisions)) !== false)
157            {
158                if ($revision == '.' || $revision == '..')
159                    continue;
160               
161                $pathInfo = pathinfo($revision);
162                $revisionID = intval(substr($pathInfo['filename'], 1));
163                if (Build::BuildExists($branchName, $revisionID))
164                {
165                    $result[$buildName][] = new Build($branchName, $revisionID);
166                }
167                else
168                {
169                    $result[$buildName][] = Build::GetBuildFromID(
170                        Build::InsertBuild($branchName, $versions[$branchName], $revisionID,
171                            Build::GetPath($branchName) . '/' . $revision));
172                }
173            }
174        }
175       
176        return $result;
177    }
178   
179    public static function BuildExists($branch, $revision)
180    {
181        $query = mysql_query(sprintf('SELECT DownloadID FROM builds WHERE
182                Branch=\'%s\' AND Revision=%d',
183            mysql_real_escape_string($branch), intval($revision)));
184        return mysql_num_rows($query) == 1;
185    }
186   
187    public static function GetBuildFromID($downloadID)
188    {
189        $query = mysql_query(sprintf('SELECT * FROM builds WHERE DownloadID=%d', intval($downloadID)));
190        if (($row = mysql_fetch_array($query)) === false || !$row[0])
191            return null;
192
193        return intval($row[0]) ? new Build($row['Branch'], $row['Revision']) : null;
194    }
195   
196    public function __get($varName)
197    {
198        $sql = sprintf('SELECT %%s FROM builds WHERE DownloadID=%d', $this->ID);
199        switch ($varName)
200        {
201            case 'Revision':
202            case 'Branch':
203                $sql = sprintf($sql, $varName);
204                break;
205
206            default:
207                return parent::__get($varName);
208        }
209       
210        $query = mysql_query($sql);
211        $row = $query ? mysql_fetch_row($query) : null;
212       
213        return $row ? $row[0] : null;
214    }
215   
216    private static function InsertBuild($branch, $version, $revision, $buildPath)
217    {
218        //Find the binary that users will get to download.
219        $installerPath = null;
220        $installerSize = 0;
221
222        //If $buildPath is a directory, it contains the installer.
223        if (is_dir($buildPath))
224        {
225            $directory = opendir($buildPath);
226           
227            while (($file = readdir($directory)) !== false)
228            {
229                $filePath = $buildPath . '/' . $file;
230                if (is_file($filePath))
231                {
232                    $pathInfo = pathinfo($filePath);
233                    if ($pathInfo['extension'] == 'exe')
234                    {
235                        $installerPath = sprintf('builds/%s/r%s/%s', $branch, $revision, $file);
236                        $installerSize = filesize($filePath);
237                        break;
238                    }
239                }
240            }
241        }
242        //If $buildPath.exe is a file, it's the installer we want.
243        else if (is_file($buildPath))
244        {
245            $installerPath = sprintf('builds/%s/%s', $branch, basename($buildPath));
246            $installerSize = filesize($buildPath);
247        }
248
249        if (empty($installerPath))
250        {
251            //It is a build in progress, don't create anything.
252            throw new Exception(sprintf('Build %s r%d is incomplete.', $branch, $revision));
253        }
254       
255        //Insert the build into the database.
256        mysql_query('START TRANSACTION');
257        mysql_query(sprintf('INSERT INTO downloads (Name, Released, `Type`, Version, PublisherID, Architecture, Filesize, Link)
258                VALUES (
259                    \'%1$s %2$s.%3$d\', \'%5$s\' , \'build\', \'%2$s.%3$d\', 1, \'any\', %4$d, \'?%6$s\'
260                )',
261            mysql_real_escape_string($branch), mysql_real_escape_string($version), intval($revision),
262            $installerSize, PhpToMySqlTimestamp(filemtime($buildPath)),
263            mysql_real_escape_string($installerPath)))
264                or die(mysql_error());
265        mysql_query(sprintf('INSERT INTO builds (DownloadID, Branch, Revision)
266                VALUES (
267                    LAST_INSERT_ID(), \'%s\', %d
268                )',
269            mysql_real_escape_string($branch), intval($revision)))
270                or die(mysql_error());
271
272        if (!mysql_affected_rows())
273            throw new Exception(sprintf('Could not create new build %s r%d. MySQL Error: %s', $path, $revision, mysql_error()));
274        $buildId = mysql_insert_id();
275       
276        mysql_query('COMMIT');
277       
278        //Ensure that only 3 builds are not superseded at any one time.
279        mysql_query('START TRANSACTION');
280       
281        //Get the latest 3 builds and concatenate them into a MySQL set.
282        $builds = array();
283        $query = mysql_query(sprintf('SELECT builds.DownloadID FROM builds
284            INNER JOIN downloads ON builds.DownloadID=downloads.DownloadID
285            WHERE Branch=\'%s\' AND Superseded=0
286            ORDER BY builds.DownloadID DESC LIMIT 3', mysql_real_escape_string($branch)));
287        while (($row == mysql_fetch_array($query)) !== false)
288            $builds[] = intval($row['DownloadID']);
289        $ignoredBuilds = implode(', ', $builds);
290       
291        //Set the builds which aren't yet superseded and not in the latest 3 builds
292        //as superseded.
293        mysql_query(sprintf('UPDATE downloads SET Superseded=1
294            WHERE DownloadID IN (
295                SELECT DownloadID FROM builds
296                    WHERE Branch=\'%s\' AND
297                    Superseded=0 AND
298                    DownloadID NOT IN (%s)
299            )',
300            mysql_real_escape_string($branch), $ignoredBuilds));
301        mysql_query('COMMIT');
302        return $buildId;
303    }
304   
305    private static function GetPath($path, $revision = null)
306    {
307        return sprintf('%s/../downloads/builds/%s%s', dirname(__FILE__), $path,
308            $revision === null ? '' : sprintf('/r%s', $revision));
309    }
310};
311?>
Note: See TracBrowser for help on using the repository browser.