root/trunk/patForms/Element/File.php

Revision 356, 25.4 kB (checked in by argh, 3 years ago)

Fixed a notice in the File element when the maxsize attribute is not set.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 <?php
2 /**
3  * File upload patForms element
4  *
5  * Upload-Element for single file upload. Handles upload and dumps
6  * the file in custom directory.
7  *
8  * Special attributes for this element
9  *  - uploaddir: destination for the uploaded file
10  *  - overwrite: Overwrite exitsing file if set to "yes"
11  *  - permissions: Set file-permissions for destination file
12  *  - usesession: Stores uploaded file information in session.
13  *    Though the user may not upload a file twice of validation of other form elements faile
14  *  - tempdir: The place to store uploaded file until finalization
15  *  - maxsize: maximum size of upload file in bytes (consider your web server's and PHP settings!)
16  *  - mimetype: Defines as many allowed filetype as you want. Supports asterisk for groups like: 'image/*'
17  *  - replacechars: use Perl-Regular expression for filename-translation
18  *
19  * $Id$
20  *
21  * @access        protected
22  * @package        patForms
23  * @subpackage    Element
24  * @author        gERD Schaufelberger <gerd@php-tools.net>
25  * @author        Sebastian Mordziol <argh@php-tools.net>
26  * @todo        change html-output if file was already uploaded (use session)
27  * @todo        make use of default attribute values
28  * @todo        fix tempdir - attribute (default should work in Windows, too)
29  */
30
31 /**
32  * error definition: defined upload directory is not a directory.
33  */
34 define( "PATFORMS_FILE_ERROR_NO_FILE_UPLOAD_DIR", 1301 );
35
36 /**
37  * error definition: defined upload directory is not writeable.
38  */
39 define( "PATFORMS_FILE_ERROR_UPLOAD_DIR_NOT_WRITEABLE", 1302 );
40
41 /**
42  * error definition: moving upload file to destination failed.
43  */
44 define( "PATFORMS_FILE_ERROR_CANNOT_MOVE_UPLOAD_FILE", 1303 );
45
46 /**
47  * error definition: value of attribute "replace" has wrong format.
48  */
49 define( "PATFORMS_FILE_ERROR_REPLACE_PREG_INVALID", 1304 );
50
51 /**
52  * error definition: tmp-dir not writable or does not exist.
53  */
54 define( "PATFORMS_FILE_ERROR_TEMPDIR_NOT_VALID", 1305 );
55
56 /**
57  * error definition: wrong format of permission attribute
58  */
59 define( "PATFORMS_FILE_ERROR_PERMISSION_ATTRIBUTE_NOT_VALID", 1306 );
60
61 /**
62  * error definition, file upload requires php.ini 'file_uploads'
63  */
64 define( "PATFORMS_FILE_ERROR_FILE_UPLOAD_OFF", 1307 );
65
66
67 /**
68  * File upload field
69  *
70  * $Id$
71  *
72  * @access        protected
73  * @package        patForms
74  * @subpackage    Element
75  * @author        gERD Schaufelberger <gerd@php-tools.net>
76  * @author        Sebastian Mordziol <argh@php-tools.net>
77  * @license        LGPL, see license.txt for details
78  */
79 class patForms_Element_File extends patForms_Element
80 {
81    /**
82     * Stores the name of the element - this is used mainly by the patForms
83     * error management and should be set in every element class.
84     * @access    public
85     */
86     var $elementName    =    "File";
87
88    /**
89     * the type of the element - set this to the type of element you are creating
90     * if you want to use the {@link patForms_Element::element2html()} method to
91     * create the final HTML tag for your element.
92     *
93     * @access    public
94     * @see        patForms_Element::element2html()
95     */
96     var $elementType    =    array(    "html"    =>    "input" );
97
98    /**
99     * set here which attributes you want to include in the element if you want to use
100     * the {@link patForms_Element::convertDefinition2Attributes()} method to automatically
101     * convert the values from your element definition into element attributes.
102     *
103     * @access    protected
104     * @see        patForms_Element::convertDefinition2Attribute()
105     */
106     var    $attributeDefinition    =    array(
107
108             "id"            =>    array(    "required"        =>    false,
109                                         "format"        =>    "string",
110                                         "outputFormats"    =>    array( "html" ),
111                                     ),
112             "name"            =>    array(    "required"        =>    true,
113                                         "format"        =>    "string",
114                                         "outputFormats"    =>    array( "html" ),
115                                         "modifiers"        =>    array( "insertSpecials" => array() ),
116                                     ),
117             "type"            =>    array(    "required"        =>    false,
118                                         "format"        =>    "string",
119                                         "outputFormats"    =>    array( "html" ),
120                                     ),
121             "title"            =>    array(    "required"        =>    false,
122                                         "format"        =>    "string",
123                                         "outputFormats"    =>    array( "html" ),
124                                         "modifiers"        =>    array( "insertSpecials" => array() ),
125                                     ),
126             "description"    =>    array(    "required"        =>    false,
127                                         "format"        =>    "string",
128                                         "outputFormats"    =>    array(),
129                                         "modifiers"        =>    array( "insertSpecials" => array() ),
130                                     ),
131             "label"            =>    array(    "required"        =>    false,
132                                         "format"        =>    "string",
133                                         "outputFormats"    =>    array(),
134                                     ),
135             "display"        =>    array(    "required"        =>    false,
136                                         "format"        =>    "string",
137                                         "default"        =>    "yes",
138                                         "outputFormats"    =>    array(),
139                                     ),
140             "edit"            =>    array(    "required"        =>    false,
141                                         "format"        =>    "string",
142                                         "default"        =>    "yes",
143                                         "outputFormats"    =>    array(),
144                                     ),
145             "required"        =>    array(    "required"        =>    false,
146                                         "format"        =>    "string",
147                                         "default"        =>    "yes",
148                                         "outputFormats"    =>    array(),
149                                     ),
150             "value"            =>    array(    "required"        =>    false,
151                                         "format"        =>    "string",
152                                         "outputFormats"    =>    array( "html" ),
153                                     ),
154             "style"            =>    array(    "required"        =>    false,
155                                         "outputFormats"    =>    array( "html" ),
156                                         "format"        =>    "string",
157                                     ),
158             "class"            =>    array(    "required"        =>    false,
159                                         "outputFormats"    =>    array( "html" ),
160                                         "format"        =>    "string",
161                                     ),
162             "onchange"        =>    array(    "required"        =>    false,
163                                         "format"        =>    "string",
164                                         "outputFormats"    =>    array( "html" ),
165                                         "modifiers"        =>    array( "insertSpecials" => array() ),
166                                     ),
167             "onclick"        =>    array(    "required"        =>    false,
168                                         "format"        =>    "string",
169                                         "outputFormats"    =>    array( "html" ),
170                                         "modifiers"        =>    array( "insertSpecials" => array() ),
171                                     ),
172             "onfocus"        =>    array(    "required"        =>    false,
173                                         "format"        =>    "string",
174                                         "outputFormats"    =>    array( "html" ),
175                                         "modifiers"        =>    array( "insertSpecials" => array() ),
176                                     ),
177             "onmouseover"    =>    array(    "required"        =>    false,
178                                         "format"        =>    "string",
179                                         "outputFormats"    =>    array( "html" ),
180                                         "modifiers"        =>    array( "insertSpecials" => array() ),
181                                     ),
182             "onmouseout"    =>    array(    "required"        =>    false,
183                                         "format"        =>    "string",
184                                         "outputFormats"    =>    array( "html" ),
185                                         "modifiers"        =>    array( "insertSpecials" => array() ),
186                                     ),
187             "onblur"        =>    array(    "required"        =>    false,
188                                         "format"        =>    "string",
189                                         "outputFormats"    =>    array( "html" ),
190                                         "modifiers"        =>    array( "insertSpecials" => array() ),
191                                     ),
192             "accesskey"        =>    array(    "required"        =>    false,
193                                         "format"        =>    "string",
194                                         "outputFormats"    =>    array( "html" ),
195                                     ),
196             "position"        =>    array(    "required"        =>    false,
197                                         "format"        =>    "int",
198                                         "outputFormats"    =>    array(),
199                                     ),
200             "tabindex"        =>    array(    "required"        =>    false,
201                                         "format"        =>    "int",
202                                         "outputFormats"    =>    array( "html" ),
203                                     ),
204             "format"        =>    array(    "required"        =>    false,
205                                         "format"        =>    "string",
206                                         "outputFormats"    =>    array(),
207                                     ),
208             "maxsize"       =>  array(  "required"      =>  false,
209                                         "format"        =>  "int",
210                                         "outputFormats" =>  array(),
211                                     ),
212             "mimetype"        =>    array(    "required"        =>    false,
213                                         "format"        =>    "array",
214                                         "outputFormats"    =>    array(),
215                                     ),
216             "uploaddir"        =>    array(    "required"        =>    false,
217                                         "format"        =>    "string",
218                                         "outputFormats"    =>    array(),
219                                     ),
220             "overwrite"        =>    array(    "required"        =>    false,
221                                         "format"        =>    "boolean",
222                                         "outputFormats"    =>    array(),
223                                     ),
224             "tempdir"        =>    array(    "required"        =>    false,
225                                         "format"        =>    "string",
226                                         "default"        =>    false,
227                                         "outputFormats"    =>    array(),
228                                     ),
229             "permissions"    =>    array(    "required"        =>    false,
230                                         "format"        =>    "string",
231                                         "default"        =>    "0666",
232                                         "outputFormats"    =>    array(),
233                                     ),
234             "replacename"    =>    array(    "required"        =>    false,
235                                         "format"        =>    "string",
236                                         "default"        =>    'i/[^a-z0-9\.]/_',
237                                         "outputFormats"    =>    array(),
238                                     ),
239             "usesession"    =>    array(    "required"        =>    false,
240                                         "format"        =>    "boolean",
241                                         "outputFormats"    =>    array(),
242                                     ),
243             "disabled"        =>    array(    "required"        =>    false,
244                                         "format"        =>    "string",
245                                         "default"        =>    "no",
246                                         "outputFormats"    =>    array( "html" ),
247                                     ),
248             "size"            =>    array(    "required"        =>    false,
249                                         "format"        =>    "number",
250                                         "default"        =>    25,
251                                         "outputFormats"    =>    array( "html" ),
252                                     ),
253         );
254
255     /**
256      *    define error codes an messages for each form element
257      *
258      *  @access private
259      *  @var    array    $validatorErrorCodes
260      */
261     var    $validatorErrorCodes  =   array(
262         "C"    =>    array(
263             1    =>    "This field is required, please complete it.",
264             2    =>    "Filename already exists - cannot overwrite file.",
265             3    =>    "The uploaded file exceeds the maximum size of [MAXSIZE].",
266             4    =>    "The uploaded file was only partially uploaded.",
267             5    =>    "Wrong Filetype (mime: '[MIMETYPE]')",
268             6    =>    "The uploaded file is empty."
269         ),
270         "de" =>    array(
271             1    =>    "Pflichtfeld. Bitte vervollstÀndigen Sie Ihre Angabe.",
272             2    =>    "Dateiname existiert bereits - die Datei kann nicht ÃŒberschrieben werden",
273             3    =>    "Die Datei ist größer als die zugelassene Maximalgröße von [MAXSIZE].",
274             4    =>    "Die Datei wurde nur teilweise hochgeladen",
275             5    =>    "Falscher Dateityp (Mime-Typ: '[MIMETYPE]')",
276             6    =>    "Die Datei ist leer."
277         ),
278         "fr" =>    array(
279             1    =>    "Ce champ est obligatoire.",
280             2    =>    "Ce fichier existe déjà - il ne peut pas être remplacé.",
281             3    =>    "La taille du fichier est plus grande que la maximum autorisé de [MAXSIZE]",
282             4    =>    "Le fichier n'a été téléchargé que partiellement",
283             5    =>    "Type de fichier incorrect (Type: '[MIMETYPE]')",
284             6    =>    "Le fichier est vide"
285         )
286     );
287
288    /**
289     * file permission - octal value
290     *
291     * This value has to be calculated from the attribute "permissions"
292     *
293     * @access private
294     * @var int $permission
295     */
296     var $permission = null;
297
298    /**
299     * temporary upload directory
300     *
301     * A place to store temporary files during session
302     *
303     * @access private
304     * @var string $tempdir
305     */
306     var $tempdir = false;
307
308    /**
309     * initialze file elemente
310     *
311     * - check temporary file upload dir required when sessions are used
312     * - check file upload in php.ini
313     *
314     * @access    private
315     * @return    mixed    $success    True on success, a patError object otherwise
316     */
317     function _init()
318     {
319         if( !ini_get( 'file_uploads' ) ) {
320             return patErrorManager::raiseError( PATFORMS_FILE_ERROR_FILE_UPLOAD_OFF,
321                                                 'File upload not possible',
322                                                 'php.ini doesn\'t allow file upload see: "file_uploads"' );
323         }
324
325         // require temporary directory if session-support is switched on
326         if( $this->useSession() )
327         {
328             // store the required flag for easy access
329             $tempdir    =    $this->attributes['tempdir'];
330
331             // use php.ini default
332             if( empty( $tempdir ) ) {
333                 $tempdir = session_save_path();
334                 if( empty( $tempdir ) ) {
335                     $tempdir = '/tmp';
336                 }
337             }
338
339             if( !is_dir( $tempdir ) && !is_writeable( $tempdir ) ) {
340                 $error = patErrorManager::raiseError(
341                     PATFORMS_FILE_ERROR_TEMPDIR_NOT_VALID,
342                     'Session support is on but cannot work',
343                     'The temporary directory "' . $tempdir . '" used in your PHP installation to '.
344                     'store session data does not exist or is not writeable. For reference, the current ' .
345                     'php.ini setting for this folder is "'.session_save_path().'", and my tempdir attribute '.
346                     'is set to "'.$this->getAttribute( 'tempdir' ).'".'
347                 );
348
349                 return $error;
350             }
351
352             $this->tempdir    =    $tempdir;
353         }
354
355         // check destination dir
356         if( !is_dir( $this->attributes['uploaddir'] ) || !is_writeable( $this->attributes['uploaddir'] ) ) {
357             return patErrorManager::raiseError( PATFORMS_FILE_ERROR_UPLOAD_DIR_NOT_WRITEABLE ,
358                                             'Upload folder invalid',
359                                             'Destination folder "' . $this->attributes['uploaddir'] . '" does not exist or is not writeable!' );
360         }
361
362         return true;
363     }
364
365    /**
366     * element creation method for the 'HTML' format in the 'default' form mode.
367     *
368     * @access    public
369     * @param    mixed    value of the element
370     * @return    mixed    $element    The element, or false if failed.
371     * @todo        check, why the value has to be stored in the attributes
372     */
373     function serializeHtmlDefault( $value )
374     {
375         $this->attributes['value']    =    $value;
376         $name        =    $this->attributes['name'];
377         $nameUpload    =    $name . '_upload';
378
379         // make sure we're a file field :)
380         $this->attributes['type']    =    'file';
381
382         // editable or not?
383         if( isset( $this->attributes['edit'] ) && $this->attributes['edit'] == 'no' ) {
384             return $this->serializeHtmlReadonly( $value );
385         }
386
387         // create element
388         $this->attributes['name']    =    $nameUpload;
389         $this->attributes['id']     =   $nameUpload;
390         $element = $this->toHtml();
391         if( patErrorManager::isError( $element ) ) {
392             return $element;
393         }
394
395         $this->attributes["name"]   =   $name;
396         $valueElement =   $this->createHiddenTag( $this->attributes["value"] );
397         /*
398         if( $this->useSession() && $this->getSessionValue( 'state' ) == 'valid' ) {
399             $atts   =   $this->attributes;
400             $atts   =   array(
401                         'value' =>  $this->attributes["value"],
402                         'type'  =>  'checkbox',
403                         'title' =>  'keep uploaded file: "'. $this->attributes["value"] .'"',
404                         'checked'   =>  'checked'
405                         );
406             $valueElement   =   $this->createTag( 'input', 'full', $atts );
407         }
408         */
409
410         // and return to sender...
411         return $valueElement . "\n" . $element;
412     }
413
414    /**
415     * element creation method for the 'HTML' format in the 'readonly' form mode.
416     * Very simple; just returns the stored element value.
417     *
418     * @access    public
419     * @param    mixed    value of the element
420     * @return    string    $value    The element's value
421     */
422     function serializeHtmlReadonly( $value )
423     {
424         $display    =    $value;
425
426         $this->getAttributesFor( $this->getFormat() );
427
428         return $display . $this->createHiddenTag( $value );
429     }
430
431    /**
432     * validates the element.
433     *
434     * @access    public
435     * @param    mixed    value of the element
436     * @return    bool    $isValid    True if element could be validated, false otherwise.
437     */
438     function validateElement( $value )
439     {
440         $name        =    $this->attributes['name'];
441         $nameUpload    =    $name . '_upload';
442
443         $empty        =    false;
444         $mime        =    false;
445         $uploade    =   false;
446
447         $error        =    UPLOAD_ERR_NO_FILE;
448         $restored    =    false;
449
450         $files      =   false;
451         if( isset( $_FILES ) ) {
452             $files = $_FILES;
453
454             if( ( $namespace = $this->getNamespace() ) && isset( $files[$namespace] ) ) {
455                 $files = $files[$namespace];
456             }
457         }
458
459         // file was just uploaded
460         if( !empty( $files ) && ( isset($files[$nameUpload] ) || isset( $files['name'][$nameUpload] ) ) ) {
461             if( !$namespace ) {
462                 $uploadFile    =    $files[$nameUpload]['tmp_name'];
463                 $error        =    $files[$nameUpload]['error'];
464                 $mime        =    $files[$nameUpload]['type'];
465                 $value        =    $this->_replaceChars($files[$nameUpload]['name']);
466                 $size        =    $files[$nameUpload]['size'];
467             } else {
468                 $uploadFile    =    $files['tmp_name'][$nameUpload];
469                 $error        =    $files[