DaPortal

<?php //$Id$
//Copyright (c) 2012-2016 Pierre Pronchery <khorben@defora.org>
//This file is part of DeforaOS Web DaPortal
//
//This program is free software: you can redistribute it and/or modify
//it under the terms of the GNU General Public License as published by
//the Free Software Foundation, version 3 of the License.
//
//This program is distributed in the hope that it will be useful,
//but WITHOUT ANY WARRANTY; without even the implied warranty of
//MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//GNU General Public License for more details.
//
//You should have received a copy of the GNU General Public License
//along with this program. If not, see <http://www.gnu.org/licenses/>.
//FIXME:
//- properly implement file deletion
//DownloadModule
class DownloadModule extends MultiContentModule
{
//public
//methods
//accessors
//DownloadModule::canPreview
public function canPreview(Engine $engine, Request $request = NULL,
Content $content = NULL, &$error = FALSE)
{
//XXX previewing is not always irrelevant
return FALSE;
}
//DownloadModule::canPublish
public function canPublish(Engine $engine, Request $request = NULL,
Content $content = NULL, &$error = FALSE)
{
$error = 'Publishing is always disabled';
return FALSE;
}
//DownloadModule::canUnpublish
public function canUnpublish(Engine $engine, Request $request = NULL,
Content $content = NULL, &$error = FALSE)
{
$error = 'Unpublishing is always disabled';
return FALSE;
}
//useful
//DownloadModule::call
public function call(Engine $engine, Request $request, $internal = 0)
{
$action = $request->getAction();
if($internal)
switch($action)
{
case 'get':
return $this->getContent($engine,
$request->getID(),
$request->getTitle(),
$request);
case 'getRoot':
return DownloadContent::getRoot($engine,
$this->getName());
case 'submit':
return $this->_callInternalSubmit(
$engine, $request);
}
else
switch($action)
{
case 'download':
case 'submit':
$action = 'call'.$action;
return $this->$action($engine,
$request);
case 'folder_new':
return $this->callFolderNew($engine,
$request);
case 'file_insert':
return $this->callSubmit($engine,
$request);
}
return parent::call($engine, $request, $internal);
}
protected function _callInternalSubmit(Engine $engine, Request $request)
{
if(($filename = $request->get('filename')) === FALSE)
return FALSE;
$parent = $this->getContent($engine, $request->getID(),
$request->getTitle(), $request);
$error = $this->_submitProcessFileDo($engine, $request, $parent,
$filename, $request->getTitle(), $content);
if($error !== FALSE)
//XXX report the error to the user instead
return $engine->log(LOG_ERR, $error);
return $content;
}
//protected
//properties
static protected $S_IFDIR = 512;
static protected $content_classes = array(
'folder' => 'FolderDownloadContent',
'file' => 'FileDownloadContent');
//queries
//IN: module_id
static protected $query_list_admin = 'SELECT
daportal_content.content_id AS id, timestamp,
daportal_user_enabled.user_id AS user_id, username,
daportal_group.group_id AS group_id, groupname,
title, daportal_content.enabled AS enabled,
daportal_content.public AS public, download_id, mode
FROM daportal_content, daportal_download, daportal_user_enabled,
daportal_group
WHERE daportal_content.content_id=daportal_download.content_id
AND daportal_content.module_id=:module_id
AND daportal_content.user_id=daportal_user_enabled.user_id
AND daportal_content.group_id=daportal_group.group_id';
//IN: module_id
static protected $query_list_admin_count = 'SELECT COUNT(*) AS count
FROM daportal_content, daportal_download, daportal_user_enabled,
daportal_group
WHERE daportal_content.content_id=daportal_download.content_id
AND daportal_content.module_id=:module_id
AND daportal_content.user_id=daportal_user_enabled.user_id
AND daportal_content.group_id=daportal_group.group_id';
//translations
protected $file_text_content_list_title = 'File list';
protected $file_text_content_list_title_by = 'Files from';
protected $file_text_content_list_title_by_group = 'Files from group';
protected $folder_text_content_list_title = 'Folder list';
protected $folder_text_content_list_title_by = 'Folders from';
protected $folder_text_content_list_title_by_group = 'Folders from group';
//methods
//essential
//DownloadModule::DownloadModule
protected function __construct($id, $name, $title = FALSE)
{
$title = ($title === FALSE) ? _('Downloads') : $title;
parent::__construct($id, $name, $title);
$this->text_content_admin = _('Downloads administration');
$this->text_content_title = _('Downloads');
}
//accessors
//DownloadModule::canUpload
protected function canUpload(Engine $engine, Request $request = NULL,
Content $content = NULL, &$error = FALSE)
{
return $this->canUpdate($engine, $request, $content, $error);
}
//DownloadModule::setContext
protected function setContext(Engine $engine = NULL,
Request $request = NULL, Content $content = NULL)
{
parent::setContext($engine, $request, $content);
switch(static::$content_class)
{
case static::$content_classes['file']:
$this->stock_content_submit = 'upload';
$this->text_content_list_title
= $this->file_text_content_list_title;
$this->text_content_list_title_by
= $this->file_text_content_list_title_by;
$this->text_content_list_title_by_group
= $this->file_text_content_list_title_by_group;
$this->text_content_submit = _('Upload');
$this->text_content_submit_content
= _('Upload file');
break;
case static::$content_classes['folder']:
$this->stock_content_submit = 'folder-new';
$this->text_content_list_title
= $this->folder_text_content_list_title;
$this->text_content_list_title_by
= $this->folder_text_content_list_title_by;
$this->text_content_list_title_by_group
= $this->folder_text_content_list_title_by_group;
$this->text_content_submit = _('Create');
$this->text_content_submit_content
= _('New folder');
break;
}
}
//useful
//calls
//DownloadModule::callDefault
protected function callDefault(Engine $engine, Request $request)
{
$class = static::$content_classes['folder'];
if($request->getID() !== FALSE)
return $this->callDisplay($engine, $request);
$root = new $class($engine, $this);
return new PageResponse($root->display($engine, $request));
}
//DownloadModule::callDownload
protected function callDownload(Engine $engine, Request $request)
{
global $config;
$error = _('Could not fetch content');
if(($id = $request->getID()) === FALSE)
return $this->callDefault($engine, new Request());
if(($content = $this->getContent($engine, $id,
$request->getTitle())) === FALSE)
return new ErrorResponse($error,
Response::$CODE_ENOENT);
if($content instanceof FileDownloadContent)
return $content->download($engine, $request);
return new ErrorResponse($error);
}
//DownloadModule::callSubmit
protected function callSubmit(Engine $engine, Request $request)
{
return parent::callSubmit($engine, $request);
}
protected function _submitContent(Engine $engine, Request $request)
{
$class = static::$content_classes['folder'];
if($request->get('type') == 'file'
&& ($parent = $request->get('parent'))
!== FALSE)
return $class::loadByDownloadID($engine, $this,
$parent);
return parent::_submitContent($engine, $request);
}
protected function _submitProcess(Engine $engine, Request $request,
Content $content)
{
//verify the request
if($request->isIdempotent())
return TRUE;
switch($request->get('type'))
{
case 'file':
return $this->_submitProcessFile($engine,
$request, $content);
default:
return parent::_submitProcess($engine, $request,
$content);
}
}
protected function _submitProcessFile(Engine $engine, Request $request,
$parent)
{
$forbidden = array('.', '..');
//XXX UNIX supports backward slashes in filenames
$delimiters = array('/', '\\');
if(!isset($_FILES['files'])
|| count($_FILES['files']['error']) == 0)
return TRUE;
//check known errors
$count = 0;
foreach($_FILES['files']['error'] as $k => $v)
{
if($v == UPLOAD_ERR_NO_FILE)
continue;
else if($v != UPLOAD_ERR_OK)
return _('An error occurred');
foreach($forbidden as $f)
if($_FILES['files']['name'][$k] == $f)
return _('Forbidden filename');
foreach($delimiters as $d)
if(strpos($_FILES['files']['name'][$k], $d)
!== FALSE)
return _('An error occurred');
$count++;
}
if($count == 0)
return _('No file uploaded');
//store each file uploaded
$errors = array();
foreach($_FILES['files']['error'] as $k => $v)
{
if($_FILES['files']['error'] == UPLOAD_ERR_NO_FILE)
continue;
$res = $this->_submitProcessFileDo($engine, $request,
$parent,
$_FILES['files']['tmp_name'][$k],
$_FILES['files']['name'][$k]);
if($res !== TRUE)
$errors[] = $res;
}
return (count($errors)) ? implode("\n", $errors) : FALSE;
}
protected function _submitProcessFileDo(Engine $engine,
Request $request, $parent, $pathname, $filename,
&$content = FALSE)
{
$class = static::$content_classes['file'];
if($filename === FALSE)
$filename = basename($pathname);
$content = new $class($engine, $this, array(
'title' => $filename, 'content' => FALSE,
'filename' => $pathname,
'parent_id' => ($parent !== FALSE)
? $parent->get('download_id') : FALSE,
'mode' => 0644));
$error = _('Internal server error');
if($content->save($engine, $request, $error) === FALSE)
return $error;
return TRUE;
}
//forms
//DownloadModule::formSubmit
protected function formSubmit(Engine $engine, Request $request)
{
$r = $this->getRequest('submit', array(
'type' => $request->get('type'),
'parent' => $request->get('parent')));
$form = new PageElement('form', array('request' => $r));
//content
$this->helperSubmitContent($engine, $request, $form);
//buttons
$this->helperSubmitButtons($engine, $request, $form);
return $form;
}
//helpers
//DownloadModule::helperActionsAdmin
protected function helperActionsAdmin(Engine $engine, Request $request)
{
//XXX duplicated from ContentModule::helperActionsAdmin
if($request->get('admin') === 0)
return FALSE;
$ret = array();
$r = $this->getRequest('admin');
$ret[] = $this->helperAction($engine, 'admin', $r,
$this->text_content_admin);
return $ret;
}
//DownloadModule::helperAdminRow
protected function helperAdminRow(Engine $engine, PageElement $row,
$res)
{
$class = ($res['mode'] & static::$S_IFDIR)
? static::$content_classes['folder']
: static::$content_classes['file'];
$content = $class::loadFromProperties($engine, $this, $res);
$r = $content->displayRow($engine);
$columns = array('id', 'title', 'enabled', 'public', 'username',
'date');
foreach($columns as $c)
$row->set($c, $r->get($c));
$stock = ($res['mode'] & static::$S_IFDIR) ? 'folder' : 'file';
$row->set('icon', new PageElement('image', array('size' => 16,
'stock' => $stock)));
}
}
?>