diff --git a/src/IDF/Form/UploadArchive.php b/src/IDF/Form/UploadArchive.php new file mode 100644 index 0000000..671a0d3 --- /dev/null +++ b/src/IDF/Form/UploadArchive.php @@ -0,0 +1,171 @@ +user = $extra['user']; + $this->project = $extra['project']; + + $this->fields['archive'] = new Pluf_Form_Field_File( + array('required' => true, + 'label' => __('Archive file'), + 'initial' => '', + 'max_size' => Pluf::f('max_upload_archive_size', 20971520), + )); + } + + + public function clean_archive() + { + $extra = strtolower(implode('|', explode(' ', Pluf::f('idf_extra_upload_ext')))); + if (strlen($extra)) $extra .= '|'; + if (!preg_match('/\.('.$extra.'png|jpg|jpeg|gif|bmp|psd|tif|aiff|asf|avi|bz2|css|doc|eps|gz|jar|mdtext|mid|mov|mp3|mpg|ogg|pdf|ppt|ps|qt|ra|ram|rm|rtf|sdd|sdw|sit|sxi|sxw|swf|tgz|txt|wav|xls|xml|war|wmv|zip)$/i', $this->cleaned_data['file'])) { + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + throw new Pluf_Form_Invalid(__('For security reasons, you cannot upload a file with this extension.')); + } + return $this->cleaned_data['file']; + } + + /** + * Validate the interconnection in the form. + */ + public function clean() + { + $conf = new IDF_Conf(); + $conf->setProject($this->project); + $onemax = array(); + foreach (explode(',', $conf->getVal('labels_download_one_max', IDF_Form_UploadConf::init_one_max)) as $class) { + if (trim($class) != '') { + $onemax[] = mb_strtolower(trim($class)); + } + } + $count = array(); + for ($i=1;$i<7;$i++) { + $this->cleaned_data['label'.$i] = trim($this->cleaned_data['label'.$i]); + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(mb_strtolower(trim($class)), + trim($name)); + } else { + $class = 'other'; + $name = $this->cleaned_data['label'.$i]; + } + if (!isset($count[$class])) $count[$class] = 1; + else $count[$class] += 1; + if (in_array($class, $onemax) and $count[$class] > 1) { + if (!isset($this->errors['label'.$i])) $this->errors['label'.$i] = array(); + $this->errors['label'.$i][] = sprintf(__('You cannot provide more than label from the %s class to an issue.'), $class); + throw new Pluf_Form_Invalid(__('You provided an invalid label.')); + } + } + return $this->cleaned_data; + } + + /** + * If we have uploaded a file, but the form failed remove it. + * + */ + function failed() + { + if (!empty($this->cleaned_data['file']) + and file_exists(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file'])) { + @unlink(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + } + } + + /** + * Save the model in the database. + * + * @param bool Commit in the database or not. If not, the object + * is returned but not saved in the database. + * @return Object Model with data set from the form. + */ + function save($commit=true) + { + if (!$this->isValid()) { + throw new Exception(__('Cannot save the model from an invalid form.')); + } + // Add a tag for each label + $tags = array(); + for ($i=1;$i<7;$i++) { + if (strlen($this->cleaned_data['label'.$i]) > 0) { + if (strpos($this->cleaned_data['label'.$i], ':') !== false) { + list($class, $name) = explode(':', $this->cleaned_data['label'.$i], 2); + list($class, $name) = array(trim($class), trim($name)); + } else { + $class = 'Other'; + $name = trim($this->cleaned_data['label'.$i]); + } + $tags[] = IDF_Tag::add($name, $this->project, $class); + } + } + // Create the upload + $upload = new IDF_Upload(); + $upload->project = $this->project; + $upload->submitter = $this->user; + $upload->summary = trim($this->cleaned_data['summary']); + $upload->changelog = trim($this->cleaned_data['changelog']); + $upload->file = $this->cleaned_data['file']; + $upload->filesize = filesize(Pluf::f('upload_path').'/'.$this->project->shortname.'/files/'.$this->cleaned_data['file']); + $upload->downloads = 0; + $upload->create(); + foreach ($tags as $tag) { + $upload->setAssoc($tag); + } + // Send the notification + $upload->notify($this->project->getConf()); + /** + * [signal] + * + * IDF_Upload::create + * + * [sender] + * + * IDF_Form_Upload + * + * [description] + * + * This signal allows an application to perform a set of tasks + * just after the upload of a file and after the notification run. + * + * [parameters] + * + * array('upload' => $upload); + * + */ + $params = array('upload' => $upload); + Pluf_Signal::send('IDF_Upload::create', 'IDF_Form_Upload', + $params); + return $upload; + } +} + diff --git a/src/IDF/Views.php b/src/IDF/Views.php index 70bbdc3..65f016f 100644 --- a/src/IDF/Views.php +++ b/src/IDF/Views.php @@ -292,6 +292,22 @@ class IDF_Views } + /** + * Download archive FAQ. + */ + public function faqArchiveFormat($request, $match) + { + $title = __('InDefero Upload Archive Format'); + $projects = self::getProjects($request->user); + return Pluf_Shortcuts_RenderToResponse('idf/faq-archive-format.html', + array( + 'page_title' => $title, + 'projects' => $projects, + ), + $request); + + } + /** * API FAQ. */ diff --git a/src/IDF/Views/Download.php b/src/IDF/Views/Download.php index 5fb49e8..1444629 100644 --- a/src/IDF/Views/Download.php +++ b/src/IDF/Views/Download.php @@ -224,11 +224,11 @@ class IDF_Views_Download } /** - * Submit a new file for download. + * Create a new file for download. */ - public $submit_precond = array('IDF_Precondition::accessDownloads', + public $create_precond = array('IDF_Precondition::accessDownloads', 'IDF_Precondition::projectMemberOrOwner'); - public function submit($request, $match) + public function create($request, $match) { $prj = $request->project; $title = __('New Download'); @@ -250,7 +250,7 @@ class IDF_Views_Download array('project' => $prj, 'user' => $request->user)); } - return Pluf_Shortcuts_RenderToResponse('idf/downloads/submit.html', + return Pluf_Shortcuts_RenderToResponse('idf/downloads/create.html', array( 'auto_labels' => self::autoCompleteArrays($prj), 'page_title' => $title, @@ -259,6 +259,39 @@ class IDF_Views_Download $request); } + /** + * Create new downloads from an uploaded archive. + */ + public $createFromArchive_precond = array('IDF_Precondition::accessDownloads', + 'IDF_Precondition::projectMemberOrOwner'); + public function createFromArchive($request, $match) + { + $prj = $request->project; + $title = __('New Downloads from Archive'); + if ($request->method == 'POST') { + $form = new IDF_Form_UploadArchive(array_merge($request->POST, $request->FILES), + array('project' => $prj, + 'user' => $request->user)); + if ($form->isValid()) { + $upload = $form->save(); + $request->user->setMessage(__('The archive has been uploaded and processed.')); + $url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index', + array($prj->shortname)); + return new Pluf_HTTP_Response_Redirect($url); + } + } else { + $form = new IDF_Form_UploadArchive(null, + array('project' => $prj, + 'user' => $request->user)); + } + return Pluf_Shortcuts_RenderToResponse('idf/downloads/createFromArchive.html', + array( + 'page_title' => $title, + 'form' => $form, + ), + $request); + } + /** * Create the autocomplete arrays for the little AJAX stuff. */ diff --git a/src/IDF/conf/idf.php-dist b/src/IDF/conf/idf.php-dist index 62fe1ce..d3293fe 100644 --- a/src/IDF/conf/idf.php-dist +++ b/src/IDF/conf/idf.php-dist @@ -495,6 +495,11 @@ $cfg['idf_strong_key_check'] = false; # always have precedence. # $cfg['max_upload_size'] = 2097152; // Size in bytes +# If a download archive is uploaded, the size of the archive is limited to 20MB. +# The php.ini upload_max_filesize and post_max_size configuration setting will +# always have precedence. +# $cfg['max_upload_archive_size'] = 20971520; // Size in bytes + # Older versions of Indefero submitted a POST request to a configured # post-commit web hook when new revisions arrived, whereas a PUT request # would have been more appropriate. Also, the payload's HMAC digest was diff --git a/src/IDF/conf/urls.php b/src/IDF/conf/urls.php index 3e2288b..8376683 100644 --- a/src/IDF/conf/urls.php +++ b/src/IDF/conf/urls.php @@ -304,6 +304,11 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/page/(.*)/$#', // ---------- Downloads ------------------------------------ +$ctl[] = array('regex' => '#^/help/archive-format/$#', + 'base' => $base, + 'model' => 'IDF_Views', + 'method' => 'faqArchiveFormat'); + $ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/$#', 'base' => $base, 'model' => 'IDF_Views_Download', @@ -332,7 +337,12 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/get/$#', $ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/create/$#', 'base' => $base, 'model' => 'IDF_Views_Download', - 'method' => 'submit'); + 'method' => 'create'); + +$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/create/archive/$#', + 'base' => $base, + 'model' => 'IDF_Views_Download', + 'method' => 'createFromArchive'); $ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/delete/$#', 'base' => $base, diff --git a/src/IDF/templates/idf/downloads/base.html b/src/IDF/templates/idf/downloads/base.html index c7e046a..248bf73 100644 --- a/src/IDF/templates/idf/downloads/base.html +++ b/src/IDF/templates/idf/downloads/base.html @@ -2,6 +2,10 @@ {block tabdownloads} class="active"{/block} {block subtabs}