[Typo3-dev] TCEmain Hook processing of uploaded files

Christoph Köpernick @ proSystem Media GmbH christoph at psysm.com
Mon Sep 26 14:26:11 CEST 2005


I´ve found the solution myself, I hope somebody could help this too.

I made a XCLASS extension for TCEmain function
checkValue_group_select_file().

For case 1:
Edit TCEform and remove multiple="multiple" doesn´t take effect, because
the JS of the element browser makes it multiple, if you add an file
through the element browser. Because I don´t want multiple files in the
array I added the following at the beginning of
checkValue_group_select_file().:

		if($valueArray[0] && $uploadedFileArray[tmp_name]) {
			unset($uploadedFileArray);
		}

If a file is already in the field, and a new one is provided the new is
discarded. If a user wants to overwrite the file he has to remove it
first by clicking on the trash (saving directly after this isn´t needed
anymore).

For case 2:
The files are removed AFTER trying to write the new files, see
#$this->removeFilesStore

So I changed $this->removeFilesStore[]=$dest.'/'.$theFile; to
unlink($dest.'/'.$theFile); Now the file is removed (unlinked)
instantly.

Here is my full XCLASS:

<?php
/** 
* User-Extension of TCEmain class
*
* @author  Christoph Koepernick <christoph at psysm.com>
*/

class ux_t3lib_TCEmain extends t3lib_TCEmain {


    function
checkValue_group_select_file($valueArray,$tcaFieldConf,$curValue,$upload
edFileArray,$status,$table,$id,$recFID)    {

            if($valueArray[0] && $uploadedFileArray[tmp_name]) {
                unset($uploadedFileArray);
            }
                

                // If any files are uploaded:
            if (is_array($uploadedFileArray) &&
                $uploadedFileArray['name'] &&
                strcmp($uploadedFileArray['tmp_name'],'none'))  {
                    $valueArray[]=$uploadedFileArray['tmp_name'];
 
$this->alternativeFileName[$uploadedFileArray['tmp_name']] =
$uploadedFileArray['name'];
            }

                // Creating fileFunc object.
            if (!$this->fileFunc)   {
                $this->fileFunc =
t3lib_div::makeInstance('t3lib_basicFileFunctions');
                $this->include_filefunctions=1;
            }
                // Setting permitted extensions.
            $all_files = Array();
            $all_files['webspace']['allow'] = $tcaFieldConf['allowed'];
            $all_files['webspace']['deny'] = $tcaFieldConf['disallowed']
? $tcaFieldConf['disallowed'] : '*';
            $all_files['ftpspace'] = $all_files['webspace'];
            $this->fileFunc->init('', $all_files);

                // If there is an upload folder defined:
            if ($tcaFieldConf['uploadfolder'])  {
                    // For logging..
                $propArr = $this->getRecordProperties($table,$id);

                    // Get destrination path:
                $dest =
$this->destPathFromUploadFolder($tcaFieldConf['uploadfolder']);

                    // If we are updating:
                if ($status=='update')  {

                        // Finding the CURRENT files listed, either from
MM or from the current record.
                    $theFileValues=array();
                    if ($tcaFieldConf['MM'])    {   // If MM relations
for the files also!
                        $dbAnalysis =
t3lib_div::makeInstance('t3lib_loadDBGroup');
 
$dbAnalysis->start('','files',$tcaFieldConf['MM'],$id);
                        reset($dbAnalysis->itemArray);
                        while
(list($somekey,$someval)=each($dbAnalysis->itemArray))    {
                            if ($someval['id']) {
                                $theFileValues[]=$someval['id'];
                            }
                        }
                    } else {
 
$theFileValues=t3lib_div::trimExplode(',',$curValue,1);
                    }   

                        // DELETE files: If existing files were found,
traverse those and register files for deletion which has been removed:
                    if (count($theFileValues))  {
                    
                            // Traverse the input values and for all
input values which match an EXISTING value, remove the existing from
$theFileValues array (this will result in an array of all the existing
files which should be deleted!)
                            
                            
                        
                        foreach($valueArray as $key => $theFile)    {
                            if ($theFile &&
!strstr(t3lib_div::fixWindowsFilePath($theFile),'/'))   {
                                $theFileValues =
t3lib_div::removeArrayEntryByValue($theFileValues,$theFile);
                            }
                        }
                        
                            // This array contains the filenames in the
uploadfolder that should be deleted:
                        foreach($theFileValues as $key => $theFile) {
                        
                            $theFile = trim($theFile);
                            if (@is_file($dest.'/'.$theFile))   {
 
#$this->removeFilesStore[]=$dest.'/'.$theFile;
                                unlink($dest.'/'.$theFile);
                            } elseif ($theFile) {
                                $this->log($table,$id,5,0,1,"Could not
delete file '%s' (does not exist). (%s)",10,array($dest.'/'.$theFile,
$recFID),$propArr['event_pid']);
                            }
                        }
                    }
                }

                    // Traverse the submitted values:
                foreach($valueArray as $key => $theFile)    {
                        // NEW FILES? If the value contains '/' it
indicates, that the file is new and should be added to the uploadsdir
(whether its absolute or relative does not matter here)
                    if
(strstr(t3lib_div::fixWindowsFilePath($theFile),'/'))    {
                            // Init:
                        $maxSize = intval($tcaFieldConf['max_size']);
                        $cmd='';
                        $theDestFile='';        // Must be cleared. Else
a faulty fileref may be inserted if the below code returns an error!!
(Change: 22/12/2000)

                            // Check various things before copying file:
                        if (@is_dir($dest) && (@is_file($theFile) ||
@is_uploaded_file($theFile)))  {       // File and destination must
exist

                                // Finding size. For safe_mode we have
to rely on the size in the upload array if the file is uploaded.
                            if (is_uploaded_file($theFile) &&
$theFile==$uploadedFileArray['tmp_name']) {
                                $fileSize = $uploadedFileArray['size'];
                            } else {
                                $fileSize = filesize($theFile);
                            }

                            if (!$maxSize || $fileSize<=($maxSize*1024))
{   // Check file size:
                                    // Prepare filename:
                                $theEndFileName =
isset($this->alternativeFileName[$theFile]) ?
$this->alternativeFileName[$theFile] : $theFile;
                                $fI =
t3lib_div::split_fileref($theEndFileName);

                                    // Check for allowed extension:
                                if
($this->fileFunc->checkIfAllowed($fI['fileext'], $dest,
$theEndFileName)) {

                                    $theDestFile =
$this->fileFunc->getUniqueName($this->fileFunc->cleanFileName($fI['file'
]), $dest);
                                    
                                        // If we have a unique
destination filename, then write the file:
                                    if ($theDestFile)   {
 
t3lib_div::upload_copy_move($theFile,$theDestFile);
                                        $this->copiedFileMap[$theFile] =
$theDestFile;
                                        clearstatcache();
                                        if (!@is_file($theDestFile))
$this->log($table,$id,5,0,1,"Copying file '%s' failed!: The destination
path (%s) may be write protected. Please make it write enabled!.
(%s)",16,array($theFile, dirname($theDestFile),
$recFID),$propArr['event_pid']);
                                    } else
$this->log($table,$id,5,0,1,"Copying file '%s' failed!: No destination
file (%s) possible!. (%s)",11,array($theFile, $theDestFile,
$recFID),$propArr['event_pid']);
                                } else
$this->log($table,$id,5,0,1,"Fileextension '%s' not allowed.
(%s)",12,array($fI['fileext'], $recFID),$propArr['event_pid']);
                            } else $this->log($table,$id,5,0,1,"Filesize
(%s) of file '%s' exceeds limit (%s).
(%s)",13,array(t3lib_div::formatSize($fileSize),$theFile,t3lib_div::form
atSize($maxSize*1024),$recFID),$propArr['event_pid']);
                        } else $this->log($table,$id,5,0,1,'The
destination (%s) or the source file (%s) does not exist.
(%s)',14,array($dest, $theFile, $recFID),$propArr['event_pid']);

                            // If the destination file was created, we
will set the new filename in the value array, otherwise unset the entry
in the value array!
                        if (@is_file($theDestFile)) {
                            $info =
t3lib_div::split_fileref($theDestFile);
                            $valueArray[$key]=$info['file']; // The
value is set to the new filename
                        } else {
                            unset($valueArray[$key]);   // The value is
set to the new filename
                        }
                    }
                }

                    // If MM relations for the files, we will set the
relations as MM records and change the valuearray to contain a single
entry with a count of the number of files!
                if ($tcaFieldConf['MM'])    {
                    $dbAnalysis =
t3lib_div::makeInstance('t3lib_loadDBGroup');
                    $dbAnalysis->tableArray['files']=array();   // dummy

                    reset($valueArray);
                    while (list($key,$theFile)=each($valueArray))   {
                            // explode files
                            $dbAnalysis->itemArray[]['id']=$theFile;
                    }
                    if ($status=='update')  {
                        $dbAnalysis->writeMM($tcaFieldConf['MM'],$id,0);
                    } else {
                        $this->dbAnalysisStore[] = array($dbAnalysis,
$tcaFieldConf['MM'], $id, 0); // This will be traversed later to execute
the actions
                    }
                    $cc=count($dbAnalysis->itemArray);
                    $valueArray = array($cc);
                }
            }


    return $valueArray;
    }

}

?>


Please write me an email if that also helps for your purpose ;)

Best regards, Christoph Köpernick


> -----Ursprüngliche Nachricht-----
> Von: typo3-dev-bounces at lists.netfielders.de [mailto:typo3-dev-
> bounces at lists.netfielders.de] Im Auftrag von Christoph Köpernick @
> proSystem Media GmbH
> Gesendet: Montag, 26. September 2005 10:54
> An: typo3-dev at lists.netfielders.de
> Betreff: [Typo3-dev] TCEmain Hook processing of uploaded files
> 
> Dear List members,
> 
> I´d like to preprocess uploaded files in a backend form. So I created
a
> hook, that works. But I got some problems with the names of uploaded
> files.
> 
> My hook names the uploaded files (only images) in this scheme
> myextkey_img_1.jpg
> myextkey_img_2.jpg
> ...
> 
> by setting
> 
> $this->uploadedFileArray['myextkey'][$id]['my'.$k.'img']['name'] =
> 'myextkey_img_'.$k.'.jpg';
> 
> Also I want to save them into an extra directory for each $id:
> 
> $TCA[$table]['columns']['my'.$k.'img']['config']['uploadfolder'] .=
> '/'.$id];
> 
> That works too.
> 
> But two strange cases occur:
> 
> 1. If an image is already in the select field of the backend form. I
> don´t click on the trash, browse for files on my PC and then submit
the
> form. The new selected image is saved with the postfix _01 and the old
> image is still in the form.
> 
> -> Maybe a <select multiple=multiple> problem? But setting multiple=0
or
> false in the TCA doesn´t make any effect. How can I get around this?
> 
> 
> 2. If an image is already in the select field of the backend form. I
do
> delete it by clicking on the trash, browse for a new image file on my
PC
> and submit. The old image is deleted and the new is saved with postfix
> _01.
> 
> -> I´ve no idea how this happens. By looking in the source of tcemain,
I
> think the old file is deleted first and then the new file is saved
(with
> calling for a unique filename).
> 
> Now I´ve to delete, save the form, and then select the new to get the
> right filenames and no problems. I´m using 3.7.0
> 
> I hope that somebody can help me or make some suggestions how to solve
> that.
> 
> Best regards, Christoph Köpernick
> 
> _______________________________________________
> Typo3-dev mailing list
> Typo3-dev at lists.netfielders.de
> http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev





More information about the TYPO3-dev mailing list