2016-12-12 15:19:47 +01:00
< ? php
/* Copyright ( C ) 2016 Xebax Christy < xebax @ wanadoo . fr >
* Copyright ( C ) 2016 Laurent Destailleur < eldy @ users . sourceforge . net >
* Copyright ( C ) 2016 Jean - François Ferry < jfefe @ aternatik . fr >
*
* 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 ; either version 3 of the License , or
* ( at your option ) any later version .
*
* 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 />.
*/
use Luracast\Restler\RestException ;
use Luracast\Restler\Format\UploadFormat ;
require_once DOL_DOCUMENT_ROOT . '/main.inc.php' ;
2017-09-28 12:14:49 +02:00
require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php' ;
2017-10-08 23:26:35 +02:00
require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php' ;
require_once DOL_DOCUMENT_ROOT . '/projet/class/task.class.php' ;
2016-12-12 15:19:47 +01:00
/**
* API class for receive files
*
* @ access protected
* @ class Documents { @ requires user , external }
*/
class Documents extends DolibarrApi
{
2017-10-06 02:42:32 +02:00
/**
* @ var array $DOCUMENT_FIELDS Mandatory fields , checked when create and update object
*/
static $DOCUMENT_FIELDS = array (
'modulepart'
);
/**
* Constructor
*/
function __construct ()
{
global $db ;
$this -> db = $db ;
}
/**
* Returns a document . Note that , this API is similar to using the wrapper link " documents.php " to download
* a file ( used for internal HTML links of documents into application ), but with no need to be into a logged session ( no need to post the session cookie ) .
*
* @ param string $module_part Name of module or area concerned by file download ( 'facture' , ... )
* @ param string $original_file Relative path with filename , relative to modulepart ( for example : IN201701 - 999 / IN201701 - 999. pdf )
* @ param int $regeneratedoc If requested document is the main document of an object , setting this to 1 ask API to regenerate document before returning it ( supported for some module_part only ) . It is no effect in other cases .
* Also , note that setting this to 1 nead write access on object .
* @ return array List of documents
*
* @ throws 500
* @ throws 501
* @ throws 400
* @ throws 401
* @ throws 200
*/
public function index ( $module_part , $original_file = '' , $regeneratedoc = 0 )
{
2017-10-07 20:21:47 +02:00
global $conf , $langs ;
2017-10-05 10:21:52 +02:00
if ( empty ( $module_part )) {
2017-10-06 02:42:32 +02:00
throw new RestException ( 400 , 'bad value for parameter modulepart' );
}
if ( empty ( $original_file )) {
throw new RestException ( 400 , 'bad value for parameter ref or subdir' );
2017-10-05 10:21:52 +02:00
}
2017-10-04 15:59:54 +02:00
2017-10-05 10:21:52 +02:00
//--- Finds and returns the document
$entity = $conf -> entity ;
2017-10-04 15:59:54 +02:00
2017-10-05 10:21:52 +02:00
$check_access = dol_check_secure_access_document ( $module_part , $original_file , $entity , DolibarrApiAccess :: $user , '' , ( $regeneratedoc ? 'write' : 'read' ));
$accessallowed = $check_access [ 'accessallowed' ];
$sqlprotectagainstexternals = $check_access [ 'sqlprotectagainstexternals' ];
$original_file = $check_access [ 'original_file' ];
2017-09-28 12:14:49 +02:00
2017-10-05 10:21:52 +02:00
if ( preg_match ( '/\.\./' , $original_file ) || preg_match ( '/[<>|]/' , $original_file ))
{
2017-10-07 13:09:31 +02:00
throw new RestException ( 401 );
}
if ( ! $accessallowed ) {
throw new RestException ( 401 );
}
// --- Generates the document
if ( $regeneratedoc )
{
$hidedetails = empty ( $conf -> global -> MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS ) ? 0 : 1 ;
$hidedesc = empty ( $conf -> global -> MAIN_GENERATE_DOCUMENTS_HIDE_DESC ) ? 0 : 1 ;
$hideref = empty ( $conf -> global -> MAIN_GENERATE_DOCUMENTS_HIDE_REF ) ? 0 : 1 ;
if ( $module_part == 'facture' || $module_part == 'invoice' )
{
require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php' ;
$this -> invoice = new Facture ( $this -> db );
$result = $this -> invoice -> fetch ( 0 , preg_replace ( '/\.[^\.]+$/' , '' , basename ( $original_file )));
if ( ! $result ) {
throw new RestException ( 404 , 'Invoice not found' );
}
2017-10-07 20:21:47 +02:00
$result = $this -> invoice -> generateDocument ( $this -> invoice -> modelpdf , $langs , $hidedetails , $hidedesc , $hideref );
2017-10-07 13:09:31 +02:00
if ( $result <= 0 ) {
throw new RestException ( 500 , 'Error generating document' );
}
}
2017-10-05 10:21:52 +02:00
}
2017-09-28 12:14:49 +02:00
2017-10-05 10:21:52 +02:00
$filename = basename ( $original_file );
$original_file_osencoded = dol_osencode ( $original_file ); // New file name encoded in OS encoding charset
2017-09-28 12:14:49 +02:00
2017-10-05 10:21:52 +02:00
if ( ! file_exists ( $original_file_osencoded ))
{
2017-10-07 13:09:31 +02:00
throw new RestException ( 404 , 'File not found' );
2017-10-05 10:21:52 +02:00
}
2017-09-28 12:14:49 +02:00
2017-10-05 10:21:52 +02:00
$file_content = file_get_contents ( $original_file_osencoded );
2017-10-07 13:09:31 +02:00
return array ( 'filename' => $filename , 'content' => base64_encode ( $file_content ), 'encoding' => 'MIME base64 (base64_encode php function, http://php.net/manual/en/function.base64-encode.php)' );
}
/**
* Return a document .
*
* @ param int $id ID of document
* @ return array Array with data of file
*
* @ throws RestException
*/
/*
2017-05-22 10:40:24 +02:00
public function get ( $id ) {
return array ( 'note' => 'xxx' );
} */
2017-10-05 10:21:52 +02:00
2017-10-07 13:09:31 +02:00
/**
* Push a file .
* Test sample 1 : { " filename " : " mynewfile.txt " , " modulepart " : " facture " , " ref " : " FA1701-001 " , " subdir " : " " , " filecontent " : " content text " , " fileencoding " : " " , " overwriteifexists " : " 0 " } .
* Test sample 2 : { " filename " : " mynewfile.txt " , " modulepart " : " medias " , " ref " : " " , " subdir " : " mysubdir1/mysubdir2 " , " filecontent " : " content text " , " fileencoding " : " " , " overwriteifexists " : " 0 " } .
*
* @ param string $filename Name of file to create ( 'FA1705-0123' )
2017-10-08 23:26:35 +02:00
* @ param string $modulepart Name of module or area concerned by file upload ( 'facture' , 'project' , 'project_task' , ... )
2017-10-07 13:09:31 +02:00
* @ param string $ref Reference of object ( This will define subdir automatically and store submited file into it )
* @ param string $subdir Subdirectory ( Only if ref not provided )
* @ param string $filecontent File content ( string with file content . An empty file will be created if this parameter is not provided )
* @ param string $fileencoding File encoding ( '' = no encoding , 'base64' = Base 64 )
* @ param int $overwriteifexists Overwrite file if exists ( 1 by default )
* @ return bool State of copy
* @ throws RestException
*/
public function post ( $filename , $modulepart , $ref = '' , $subdir = '' , $filecontent = '' , $fileencoding = '' , $overwriteifexists = 0 )
{
global $db , $conf ;
/* var_dump ( $modulepart );
2017-05-20 15:52:36 +02:00
var_dump ( $filename );
var_dump ( $filecontent );
exit ; */
2017-10-05 10:21:52 +02:00
2017-10-08 23:26:35 +02:00
if ( empty ( $modulepart ))
{
throw new RestException ( 400 , 'Modulepart not provided.' );
}
2016-12-12 15:19:47 +01:00
2017-10-07 13:09:31 +02:00
if ( ! DolibarrApiAccess :: $user -> rights -> ecm -> upload ) {
throw new RestException ( 401 );
}
2016-12-12 15:19:47 +01:00
2017-10-07 13:09:31 +02:00
$newfilecontent = '' ;
if ( empty ( $fileencoding )) $newfilecontent = $filecontent ;
if ( $fileencoding == 'base64' ) $newfilecontent = base64_decode ( $filecontent );
2016-12-12 15:19:47 +01:00
2017-05-20 15:52:36 +02:00
$original_file = dol_sanitizeFileName ( $filename );
2016-12-12 15:19:47 +01:00
2017-05-20 15:52:36 +02:00
// Define $uploadir
$object = null ;
$entity = $user -> entity ;
if ( $ref )
2016-12-12 15:19:47 +01:00
{
2017-10-06 02:42:32 +02:00
if ( $modulepart == 'facture' || $modulepart == 'invoice' )
{
$modulepart = 'facture' ;
2017-10-08 23:26:35 +02:00
$object = new Facture ( $this -> db );
}
elseif ( $modulepart == 'project' )
{
$object = new Project ( $this -> db );
}
elseif ( $modulepart == 'task' || $modulepart == 'project_task' )
{
$modulepart = 'project_task' ;
$object = new Task ( $this -> db );
$task_result = $object -> fetch ( '' , $ref );
// Fetching the tasks project is required because its out_dir might be a subdirectory of the project
if ( $task_result > 0 )
{
$project_result = $object -> fetch_projet ();
if ( $project_result >= 0 )
{
$tmpreldir = dol_sanitizeFileName ( $object -> project -> ref ) . '/' ;
}
}
else
{
throw new RestException ( 500 , 'Error while fetching Task ' . $ref );
}
}
// TODO Implement additional moduleparts
else
{
throw new RestException ( 500 , 'Modulepart ' . $modulepart . ' not implemented yet.' );
}
if ( is_object ( $object ))
{
2017-10-06 02:42:32 +02:00
$result = $object -> fetch ( '' , $ref );
2017-10-08 23:26:35 +02:00
if ( $result == 0 )
{
throw new RestException ( 500 , " Object with ref ' " . $ref . '" was not found.' );
}
elseif ( $result < 0 )
{
throw new RestException ( 500 , 'Error while fetching object.' );
}
2017-10-06 02:42:32 +02:00
}
if ( ! ( $object -> id > 0 ))
{
throw new RestException ( 500 , 'The object ' . $modulepart . " with ref ' " . $ref . " ' was not found. " );
}
2017-10-08 23:26:35 +02:00
$tmp = dol_check_secure_access_document ( $modulepart , $tmpreldir . dol_sanitizeFileName ( $object -> ref ), $entity , DolibarrApiAccess :: $user , $ref , 'write' );
2017-10-06 02:42:32 +02:00
$upload_dir = $tmp [ 'original_file' ];
if ( empty ( $upload_dir ) || $upload_dir == '/' )
{
throw new RestException ( 500 , 'This value of modulepart does not support yet usage of ref. Check modulepart parameter or try to use subdir parameter instead of ref.' );
}
2016-12-12 15:19:47 +01:00
}
2017-05-20 15:52:36 +02:00
else
2016-12-12 15:19:47 +01:00
{
2017-10-06 02:42:32 +02:00
if ( $modulepart == 'invoice' ) $modulepart = 'facture' ;
2017-10-05 10:21:52 +02:00
2017-10-06 02:42:32 +02:00
$tmp = dol_check_secure_access_document ( $modulepart , $subdir , $entity , DolibarrApiAccess :: $user , '' , 'write' );
$upload_dir = $tmp [ 'original_file' ];
2017-05-20 15:52:36 +02:00
2017-10-06 02:42:32 +02:00
if ( empty ( $upload_dir ) || $upload_dir == '/' )
{
throw new RestException ( 500 , 'This value of modulepart does not support yet usage of ref. Check modulepart parameter or try to use subdir parameter instead of ref.' );
}
2016-12-12 15:19:47 +01:00
}
2017-10-05 10:21:52 +02:00
2017-05-20 15:52:36 +02:00
$upload_dir = dol_sanitizePathName ( $upload_dir );
2017-10-05 10:21:52 +02:00
2017-05-21 14:06:43 +02:00
$destfile = $upload_dir . '/' . $original_file ;
$destfiletmp = DOL_DATA_ROOT . '/admin/temp/' . $original_file ;
dol_delete_file ( $destfiletmp );
2017-10-05 10:21:52 +02:00
2017-10-06 02:42:32 +02:00
if ( ! dol_is_dir ( $upload_dir )) {
throw new RestException ( 401 , 'Directory not exists : ' . $upload_dir );
}
2017-10-05 10:21:52 +02:00
2017-10-06 02:42:32 +02:00
if ( ! $overwriteifexists && dol_is_file ( $destfile ))
{
throw new RestException ( 500 , " File with name ' " . $original_file . " ' already exists. " );
}
2017-10-05 10:21:52 +02:00
2017-10-06 02:42:32 +02:00
$fhandle = @ fopen ( $destfiletmp , 'w' );
if ( $fhandle )
{
$nbofbyteswrote = fwrite ( $fhandle , $newfilecontent );
fclose ( $fhandle );
@ chmod ( $destfiletmp , octdec ( $conf -> global -> MAIN_UMASK ));
}
else
{
throw new RestException ( 500 , " Failed to open file ' " . $destfiletmp . " ' for write " );
}
2016-12-12 15:19:47 +01:00
2017-10-06 02:42:32 +02:00
$result = dol_move ( $destfiletmp , $destfile , 0 , $overwriteifexists , 1 );
return $result ;
}
/**
* Validate fields before create or update object
*
* @ param array $data Array with data to verify
* @ return array
* @ throws RestException
*/
function _validate_file ( $data ) {
$result = array ();
foreach ( Documents :: $DOCUMENT_FIELDS as $field ) {
if ( ! isset ( $data [ $field ]))
throw new RestException ( 400 , " $field field missing " );
$result [ $field ] = $data [ $field ];
}
return $result ;
}
2016-12-12 15:19:47 +01:00
}