histogram: Make histograms crash less
[ninja.git] / application / controllers / upload.php
blob7caa0c25273ee979ce6514fb82f7ee2965a2ff34
1 <?php defined('SYSPATH') OR die('No direct access allowed.');
2 /**
3 * Controller to handle widget upload
5 * @package NINJA
6 * @author op5 AB
7 * @license GPL
8 * @copyright 2009 op5 AB
9 * op5, and the op5 logo are trademarks, servicemarks, registered servicemarks
10 * or registered trademarks of op5 AB.
11 * All other trademarks, servicemarks, registered trademarks, and registered
12 * servicemarks mentioned herein may be the property of their respective owner(s).
13 * The information contained herein is provided AS IS with NO WARRANTY OF ANY
14 * KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY, AND FITNESS FOR A
15 * PARTICULAR PURPOSE.
17 class Upload_Controller extends Authenticated_Controller
19 public function __construct()
21 parent::__construct();
22 if (!Auth::instance()->authorized_for('host_view_all')) {
23 # redirect to default start page if not
24 # properly authorized
25 return url::redirect(Kohana::config('routes.logged_in_default'));
29 /**
30 * Index method
32 public function index()
34 $this->template->content = $this->add_view('upload/index');
35 $content = $this->template->content;
36 $this->template->title = _('Widget Upload');
37 $this->template->disable_refresh = true;
39 $this->xtra_js[] = $this->add_path('upload/js/upload.js');
40 $this->xtra_css[] = $this->add_path('upload/css/upload.css');
43 /**
44 * Take careof the uploaded widget file
46 public function handle_upload()
48 $this->template->content = $this->add_view('upload/uploaded');
49 $ct = $this->template->content;
50 $this->template->title = _('Widget Upload');
51 $this->template->disable_refresh = true;
53 if (!isset($_FILES['upload_file'])) {
54 return url::redirect(Router::$controller.'/file_upload');
57 # assumes upload directory exists with read/write permissions
58 $savepath = Kohana::config('upload.directory');
60 if (!upload::valid($_FILES['upload_file']) || !upload::type($_FILES['upload_file'], array('zip'))) {
61 $ct->err_msg = _("Uploaded file doesn't seem to be valid - aborting.");
62 return;
65 $file = $_FILES['upload_file'];
67 upload::save($file, $file['name'], $savepath);
69 $widget_name = false;
70 $folders = array();
71 $files = array();
72 $manifest = false;
73 $friendly_name = false;
75 $zip = zip::instance($savepath.$file['name']);
76 if (($list = $zip->listContent()) == 0) {
77 $ct->err_msg = sprintf(_("Error: %s"), $zip->errorInfo(true));
78 unlink($savepath.$file['name']);
79 return;
82 foreach ($list as $index => $content) {
83 if (strstr($content['filename'], '__')) {
84 continue;
86 if ($content['index'] == 0 && $content['folder'] == 1) {
87 # stash name
88 $widget_name = str_replace('/', '', $content['filename']);
90 if ($content['folder'] == 1) {
91 $folders[] = $content['filename'];
92 } else {
93 $files[] = $content['filename'];
97 $level = 0;
98 $errors = false;
99 $erray = false;
100 $classfile = false;
101 if (!empty($folders)) {
102 # if zipfile is v 1
103 foreach ($folders as $f) {
104 $level++;
105 foreach ($files as $c) {
106 $c_name = str_replace($f, '', $c);
107 if (strstr($c_name, '__')) {
108 continue;
111 $fileinfo = pathinfo($c_name);
113 if (!strstr($c_name, '/')) {
114 # found a file
115 if ($level == 1 && $fileinfo['extension'] == 'php') {
116 # Check for the class file
117 if ($c_name == $widget_name.'.'.$fileinfo['extension']) {
118 $classfile = $c_name;
120 } elseif ($level == 1 && $fileinfo['extension'] == 'xml') {
121 # should be xml manifest file
122 $manifest = $c_name;
127 } else {
128 # if zipfile is v 2
129 $widget_name = strtolower($file['name']);
130 $widget_name = str_replace('.zip', '', $widget_name);
131 foreach($files as $c) {
132 if ($c == $widget_name.'/'.$widget_name.'.php') {
133 $classfile = $widget_name.'.php';
135 if($c == $widget_name.'/manifest.xml') {
136 $manifest = 'manifest.xml';
141 if (empty($manifest)) {
142 $errors++;
143 $erray[] = _('Found no manifest file');
145 if (empty($classfile)) {
146 $errors++;
147 $erray[] = _('Found no class file');
150 $msg = '';
151 $ct->widget_name = _('Widget name').': '.$widget_name."<br />";
152 if (empty($errors) && !empty($classfile)) {
153 #$msg .= sprintf(_("Initial checks turned out ok - Unpacking...%s"), '<br />');
154 } else {
155 $ct->err_msg = sprintf(_("Found %s errors:"), $errors);
156 $ct->erray = $erray;
157 unlink($savepath.$file['name']);
158 self::_rrmdir($savepath.$widget_name);
159 return;
162 if (!$list = $zip->extract(PCLZIP_OPT_PATH, $savepath)) {
163 $ct->err_msg = sprintf(_("Error: %s"), $zip->errorInfo(true));
164 unlink($savepath.$file['name']);
165 self::_rrmdir($savepath.$widget_name);
166 return;
169 # check widget class file
170 $classfile = file($savepath.$widget_name.'/'.$widget_name.'.php');
172 $is_correct_classname = false;
173 foreach ($classfile as $line) {
174 if (strstr($line, 'class ') && strstr($line, ' extends widget_Core')) {
175 $line = str_replace('class', '', $line);
176 $line = str_replace('{', '', $line);
177 $line = str_replace(' extends widget_Core', '', $line);
178 $line = trim($line);
179 if ($line !== ucfirst($widget_name).'_Widget') {
180 $errors++;
181 $erray[] = _('Widget classname does not meet requirements');
186 if (!empty($erray)) {
187 $ct->err_msg = sprintf(_("Found %s errors:"), $errors);
188 $ct->erray = $erray;
189 unlink($savepath.$file['name']);
190 self::_rrmdir($savepath.$widget_name);
191 return;
192 } else {
193 #$msg .= sprintf(_("Everything seems ok. Let's install this widget. %s"), '<br />');
196 # load manifest
197 $xml = simplexml_load_file($savepath.$widget_name.'/'.$manifest);
198 if ($xml === false) {
199 $ct->err_msg = _('Unable to load manifest file');
200 unlink($savepath.$file['name']);
201 self::_rrmdir($savepath.$widget_name);
202 return;
205 $friendly_name = (string)$xml->Friendly_name;
206 $description = (string)$xml->description;
207 $version = (string)$xml->version;
208 $pagename = (string)$xml->page; # should be tac/index but we don't care for now
210 $data = Ninja_widget_Model::get($pagename, $widget_name);
212 $custom_dir = APPPATH.Kohana::config('widget.custom_dirname');
214 $widget_ok = false;
215 $is_upgrade = false;
216 if ($data !== false) {
217 # widget already exists - compare versions
218 $manifestpath = $custom_dir.$widget_name.'/'.$manifest;
219 if (!file_exists($manifestpath)) {
220 # actually, it appears to be gone/broken, so let's upgrade
221 $widget_ok = true;
223 else {
224 $check_xml = @simplexml_load_file($manifestpath);
225 if ($check_xml !== false) {
226 $old_version = $check_xml->version;
227 if ($version > $old_version) {
228 $widget_ok = true;
232 $is_upgrade = $widget_ok;
233 } else {
234 $widget_ok = true;
237 if (!$widget_ok) {
238 $ct->err_msg = _('Error: A widget by this name already exists');
239 unlink($savepath.$file['name']);
240 self::_rrmdir($savepath.$widget_name);
241 return;
245 if (!is_writable($custom_dir)) {
246 sprintf(_('Widget custom dir (%s) is not writable - please modify and try again'), $custom_dir);
249 exec('cp -av '.$savepath.$widget_name.'/ '.$custom_dir, $output, $retval);
251 if ($retval != 0) {
252 $ct->err_msg = _('Error: Unable to copy widget');
253 unlink($savepath.$file['name']);
254 self::_rrmdir($savepath.$widget_name);
255 return;
258 if (file_exists($savepath.$file['name']));
259 unlink($savepath.$file['name']);
260 self::_rrmdir($savepath.$widget_name);
262 $save = Ninja_widget_Model::install($pagename, $widget_name, $friendly_name);
263 if ($save || $is_upgrade) {
264 $msg .= sprintf(_("OK, saved widget to db%s"), '<br />');
265 } else {
266 $ct->err_msg = _("Unable to save widget - maybe it's already installed?");
267 if (file_exists($savepath.$file['name']))
268 unlink($savepath.$file['name']);
269 self::_rrmdir($savepath.$widget_name);
270 return;
273 $ct->final_msg = sprintf(_('This widget should now be properly installed.%s
274 Please reload Tactical overview and enable the widget in the widget menu.'), '<br />');
275 $ct->msg = $msg;
280 * Simple method to recursively remove a
281 * directory and all containing files
283 public function _rrmdir($dir) {
284 if (is_dir($dir)) {
285 $objects = scandir($dir);
286 foreach ($objects as $object) {
287 if ($object != "." && $object != "..") {
288 if (filetype($dir."/".$object) == "dir") {
289 self::_rrmdir($dir."/".$object);
290 } else {
291 unlink($dir."/".$object);
295 reset($objects);
296 rmdir($dir);