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

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