Web · Wiki · Activities · Blog · Lists · Chat · Meeting · Bugs · Git · Translate · Archive · People · Donate
1
<?php
2
/* ***** BEGIN LICENSE BLOCK *****
3
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
 *
5
 * The contents of this file are subject to the Mozilla Public License Version
6
 * 1.1 (the "License"); you may not use this file except in compliance with
7
 * the License. You may obtain a copy of the License at
8
 * http://www.mozilla.org/MPL/
9
 *
10
 * Software distributed under the License is distributed on an "AS IS" basis,
11
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
 * for the specific language governing rights and limitations under the
13
 * License.
14
 *
15
 * The Original Code is addons.mozilla.org site.
16
 *
17
 * The Initial Developer of the Original Code is
18
 * The Mozilla Foundation.
19
 * Portions created by the Initial Developer are Copyright (C) 2006
20
 * the Initial Developer. All Rights Reserved.
21
 *
22
 * Contributor(s):
23
 *   Andrei Hajdukewycz <sancus@off.net> (Original Author)
24
 *   Justin Scott <fligtar@gmail.com>
25
 *   Frederic Wenzel <fwenzel@mozilla.com>
26
 *
27
 * Alternatively, the contents of this file may be used under the terms of
28
 * either the GNU General Public License Version 2 or later (the "GPL"), or
29
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30
 * in which case the provisions of the GPL or the LGPL are applicable instead
31
 * of those above. If you wish to allow use of your version of this file only
32
 * under the terms of either the GPL or the LGPL, and not to allow others to
33
 * use your version of this file under the terms of the MPL, indicate your
34
 * decision by deleting the provisions above and replace them with the notice
35
 * and other provisions required by the GPL or the LGPL. If you do not delete
36
 * the provisions above, a recipient may use your version of this file under
37
 * the terms of any one of the MPL, the GPL or the LGPL.
38
 *
39
 * ***** END LICENSE BLOCK ***** */
40
41
class DownloadsController extends AppController
42
{
43
    var $name = 'Downloads';
44
    var $beforeFilter = array('getNamedArgs', '_checkSandbox');
45
    var $uses = array('Addon', 'File', 'Translation');
46
    var $components = array('Amo', 'Session');
47
    var $namedArgs = true;
48
49
    var $securityLevel = 'low';
50
51
    function beforeFilter() {
52
        // Disable ACLs because this controller is entirely public.
53
        $this->SimpleAuth->enabled = false;
54
        $this->SimpleAcl->enabled = false;
55
    }
56
    
57
    function file($id = null, $type = 'xpi') {
58
        
59
        if (empty($this->namedArgs['update']))
60
            $this->namedArgs['update'] = null;
61
        
62
        $this->Amo->clean($id);
63
        $this->layout=null;
64
        if (!$id || !is_numeric($id)) {
65
            $this->flash(sprintf(___('Missing argument: %s'), 'file_id'), '/', 3);
66
            return;
67
        }
68
        
69
        $file_data = $this->File->FindbyId($id);
70
        
71
        if (!empty($file_data)) {
72
            
73
            $this->Addon->unbindFully();
74
            $addon_data = $this->Addon->FindbyId($file_data['Version']['addon_id']);
75
            
76
            $file_loc = REPO_PATH . '/' . $file_data['Version']['addon_id'] . '/' . $file_data['File']['filename'];
77
                   
78
            // If add-on is in sandbox, make sure sandbox is enabled. If disabled, make sure admin or author.
79
            // If _GET['confirmed'] exists, then a user confirmed a sandbox download via JS, bug 441739
80
            if (($addon_data['Addon']['status'] == STATUS_SANDBOX ||
81
                 $addon_data['Addon']['status'] == STATUS_NOMINATED ||
82
                 $file_data['File']['status'] == STATUS_PENDING)
83
                 && !$this->Session->check('User') && !isset($_GET['confirmed'])) {
84
                
85
                $target_url = str_replace(LANG . '/' . APP_SHORTNAME . '/','',$this->params['url']['url']);
86
                $this->redirect('/users/login?to=' . urlencode($target_url) . "&m=1");
87
                return;
88
            } elseif ($addon_data['Addon']['status'] == STATUS_DISABLED &&
89
                !$this->Amo->checkOwnership($addon_data['Addon']['id'])) {
90
                
91
                $this->flash(___('This add-on is disabled'), '/', 3);
92
                return;
93
            }
94
        } else {
95
            $this->flash(___('Add-on not found!'), '/', 3);
96
            return;
97
        }
98
        
99
        if (file_exists($file_loc))
100
            $this->set('fileLoc', $file_loc);    
101
        else {
102
            $this->flash(___('Add-on not found!'), '/', 3);
103
            return;
104
        }
105
        
106
            $forceLocal = false;
107
            $this->set('attachment', false);
108
        
109
        $this->set('fileName', $file_data['File']['filename']);
110
        
111
        if (!DEV && !$forceLocal && $addon_data['Addon']['status'] != STATUS_DISABLED
112
            && $file_data['File']['status'] != STATUS_DISABLED
113
            && (strtotime($file_data['File']['datestatuschanged']) <= strtotime('-'.MIRROR_DELAY.' minutes'))) {
114
            // serve file from releases mirror only if we are not in dev mode
115
            // and if the file is public and sufficient time has passed to allow
116
            // its propagation to the mirror system
117
            $this->forceCache();
118
            $this->redirect(FILES_HOST . '/' . $addon_data['Addon']['id'] . '/' . $file_data['File']['filename']);
119
            return;    
120
        } else {
121
            // serve file locally
122
            $this->disableCache();
123
            $this->render('file');
124
        }
125
    }
126
    
127
    /**
128
     * Retrieves public file for latest version of an add-on, regardless of compatibility
129
     * Example URL: /downloads/latest/1865/type:attachment/platform:5/
130
     * @param int $addon_id the add-on id
131
     */
132
    function latest($addon_id) {
133
        $platform_id = (!empty($this->namedArgs['platform']) && is_numeric($this->namedArgs['platform'])) ? $this->namedArgs['platform'] : null;
134
        
135
        $type = !empty($this->namedArgs['type']) ? $this->namedArgs['type'] : 'xpi';
136
        
137
        // Get the id of the latest public file
138
        $file_id = $this->File->getLatestFileByAddonId($addon_id, $platform_id);
139
        $file_data = $this->File->findById($file_id);
140
        
141
        if (!empty($file_id)) {
142
            // Use normal download method if file is found
143
            $target = "/downloads/file/{$file_id}/{$type}/{$file_data['File']['filename']}";
144
            if (count($this->params['url']) > 1) { // re-append query string
145
                $getvars = array();
146
                foreach ($this->params['url'] as $k => $v) {
147
                    if ($k == 'url') continue;
148
                    $getvars[] = "$k=$v";
149
                }
150
                $qs = implode(',', $getvars);
151
                $target .= "?$qs";
152
            }
153
            $this->redirect($target);
154
        }
155
        else {
156
            // File wasn't found
157
            $this->flash(___('Add-on not found!'), '/', 3);
158
        }
159
    }
160
}   
161
162
?>