2020-10-21 00:47:26 +02:00
< ? php
namespace EGroupware\Filemanager\Sharing ;
2020-10-21 17:13:37 +02:00
use EGroupware\Api\Etemplate ;
use EGroupware\Api\Json ;
2020-10-21 00:47:26 +02:00
use EGroupware\Api\Vfs ;
2021-03-03 22:29:56 +01:00
use EGroupware\Api\Translation ;
2020-10-21 00:47:26 +02:00
use EGroupware\Api\Vfs\Sharing ;
use EGroupware\Api\Vfs\UploadSharingUi ;
class HiddenUpload extends AnonymousList
{
/**
* Get active view - override so it points to this class
*
* @ return string
*/
public static function get_view ()
{
return array ( new HiddenUpload (), 'listview' );
}
/**
* Filemanager listview
*
* Override to customize for sharing with a hidden upload directory .
* Everything not in the upload directory is readonly , but we make it look like you can upload .
* The upload directory is not shown .
*
* @ param array $content
* @ param string $msg
*/
function listview ( array $content = null , $msg = null )
{
2020-10-21 17:13:37 +02:00
$this -> etemplate = $this -> etemplate ? $this -> etemplate : new Etemplate ( static :: LIST_TEMPLATE );
2020-10-21 00:47:26 +02:00
2021-03-12 01:00:16 +01:00
if ( isset ( $GLOBALS [ 'egw' ] -> sharing ) && array_key_exists ( Vfs\Sharing :: get_token (), $GLOBALS [ 'egw' ] -> sharing ) &&
$GLOBALS [ 'egw' ] -> sharing [ Vfs\Sharing :: get_token ()] -> has_hidden_upload ())
2020-10-21 00:47:26 +02:00
{
// Tell client side that the path is actually writable
$content [ 'initial_path_readonly' ] = false ;
// No new anything
$this -> etemplate -> disableElement ( 'nm[new]' );
$this -> etemplate -> setElementAttribute ( 'nm[button][createdir]' , 'readonly' , true );
// Take over upload, change target and conflict strategy
$path = Vfs :: concat ( self :: get_home_dir (), Sharing :: HIDDEN_UPLOAD_DIR );
2022-10-11 18:19:30 +02:00
$this -> etemplate -> setElementAttribute ( 'nm[upload]' , 'onFinishOne' , " app.filemanager.hiddenUploadOnOne " );
// Not a real attribute, but we need to make sure we always upload to the correct place
$this -> etemplate -> setElementAttribute ( 'nm[upload]' , 'uploadPath' , $path );
2020-10-21 00:47:26 +02:00
}
return parent :: listview ( $content , $msg );
}
/**
* Deal with an uploaded file .
* Overridden from the parent to change the message and message type
*
* @ param string $action Should be 'upload'
* @ param $selected Array of file information
* @ param string $dir Target directory
2021-04-28 22:19:51 +02:00
* @ param string [] $props ui_path => path the sharing UI is running eg . " /egroupware/share.php/<token> "
2020-10-21 00:47:26 +02:00
* @ param string [] $arr Result
*
* @ throws Api\Exception\AssertionFailed
*/
protected static function handle_upload_action ( string $action , $selected , $dir , $props , & $arr )
{
2021-03-03 22:29:56 +01:00
Translation :: add_app ( 'filemanager' );
2020-10-21 00:47:26 +02:00
$vfs = Vfs :: mount ();
2021-04-28 22:19:51 +02:00
$GLOBALS [ 'egw' ] -> sharing [ Sharing :: get_token ( $props [ 'ui_path' ])] -> redo ();
2021-03-16 14:02:46 +01:00
parent :: handle_upload_action ( $action , $selected , $dir , null , $arr );
2023-07-25 00:28:31 +02:00
// Parent upload action ruins our mount and says the upload failed.
// Do the mount again
$GLOBALS [ 'egw' ] -> sharing [ Sharing :: get_token ( $props [ 'ui_path' ])] -> redo ();
// Check ourselves for success
foreach ( $selected as $filekey => $file_info )
{
if ( ! is_array ( $file_info ))
{
continue ;
}
if ( $arr [ 'uploaded' ][ $filekey ] && Vfs :: stat ( $arr [ 'uploaded' ][ $filekey ][ 'path' ]))
{
// success
$arr [ 'files' ] ++ ;
$arr [ 'errs' ] -- ;
}
}
if ( $arr [ 'files' ])
2021-03-16 14:02:46 +01:00
{
2023-07-25 00:28:31 +02:00
$arr [ 'msg' ] = lang ( " The uploaded file is only visible to the person sharing these files with you, not to yourself or other people knowing this sharing link. " );
2021-03-16 14:02:46 +01:00
$arr [ 'type' ] = 'notice' ;
}
else
{
$arr [ 'type' ] = 'error' ;
}
2020-10-21 00:47:26 +02:00
}
protected function is_hidden_upload_dir ( $directory )
{
if ( ! isset ( $GLOBALS [ 'egw' ] -> sharing )) return false ;
// Just hide anything that is 'Upload' mounted where we expect, not just this share, to avoid exposing when
// more than one share is used
$mounts = Vfs :: mount ();
return Vfs :: is_dir ( $directory ) && '/' . Vfs :: basename ( $directory ) == Sharing :: HIDDEN_UPLOAD_DIR && $mounts [ $directory ];
}
/**
* Callback to fetch the rows for the nextmatch widget
*
* @ param array $query
* @ param array & $rows
* @ return int
*
* @ throws Api\Json\Exception
*/
function get_rows ( & $query , & $rows )
{
2021-03-16 14:02:46 +01:00
$hidden_upload = ( isset ( $GLOBALS [ 'egw' ] -> sharing ) && array_key_exists ( Vfs\Sharing :: get_token ( $_SERVER [ 'HTTP_REFERER' ]), $GLOBALS [ 'egw' ] -> sharing ) &&
$GLOBALS [ 'egw' ] -> sharing [ Sharing :: get_token ( $_SERVER [ 'HTTP_REFERER' ])] -> has_hidden_upload ());
2020-10-21 00:47:26 +02:00
// Not allowed in hidden upload dir
$check_path = Sharing :: HIDDEN_UPLOAD_DIR . ( substr ( $query [ 'path' ], - 1 ) == '/' ? '/' : '' );
if (( $length = strlen ( $check_path )) && ( substr ( $query [ 'path' ], - $length ) === $check_path ))
{
// only redirect, if it would be to some other location, gives redirect-loop otherwise
if ( $query [ 'path' ] != ( $path = static :: get_home_dir ()))
{
// we will leave here, since we are not allowed, go back to root
// TODO: Give message about it, redirect to home dir
}
$rows = array ();
return 0 ;
}
// Get file list from parent
$total = parent :: get_rows ( $query , $rows );
if ( ! $hidden_upload )
{
return $total ;
}
// tell client-side that this directory is writeable - allows upload + button
2020-10-21 17:13:37 +02:00
$response = Json\Response :: get ();
2020-10-21 00:47:26 +02:00
$response -> call ( 'app.filemanager.set_readonly' , $query [ 'path' ], false );
// Hide the hidden upload directory, mark everything else as readonly
foreach ( $rows as $key => & $row )
{
if ( $this -> is_hidden_upload_dir ( $row [ 'path' ]))
{
unset ( $rows [ $key ]);
$total -- ;
continue ;
}
$row [ 'class' ] .= 'noEdit noDelete ' ;
}
return $total ;
}
}