source: trunk/phpgwapi/inc/class.vfs_sql.inc.php @ 1855

Revision 1855, 71.8 KB checked in by amuller, 14 years ago (diff)

Ticket #597 - Melhoria do FM, Implementação do arquivamento

  • Property svn:eol-style set to native
  • Property svn:executable set to *
Line 
1<?php
2  /**************************************************************************\
3  * eGroupWare API - VFS                                                     *
4  * This file written by Jason Wies (Zone) <zone@phpgroupware.org>           *
5  * This class handles file/dir access for eGroupWare                        *
6  * Copyright (C) 2001 Jason Wies                                            *
7  * -------------------------------------------------------------------------*
8  * This library is part of the eGroupWare API                               *
9  * http://www.egroupware.org/api                                            *
10  * ------------------------------------------------------------------------ *
11  * This library is free software; you can redistribute it and/or modify it  *
12  * under the terms of the GNU Lesser General Public License as published by *
13  * the Free Software Foundation; either version 2.1 of the License,         *
14  * or any later version.                                                    *
15  * This library is distributed in the hope that it will be useful, but      *
16  * WITHOUT ANY WARRANTY; without even the implied warranty of               *
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     *
18  * See the GNU Lesser General Public License for more details.              *
19  * You should have received a copy of the GNU Lesser General Public License *
20  * along with this library; if not, write to the Free Software Foundation,  *
21  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA            *
22  \**************************************************************************/
23
24
25        /*!
26        @class vfs
27        @abstract Virtual File System with SQL backend
28        @description Authors: Zone
29        */
30
31        /* These are used in calls to extra_sql () */
32        define ('VFS_SQL_SELECT', 1);
33        define ('VFS_SQL_DELETE', 2);
34        define ('VFS_SQL_UPDATE', 4);
35
36        class vfs extends vfs_shared
37        {
38                var $working_id;
39                var $working_lid;
40                var $my_home;
41                var $meta_types;
42                var $now;
43                var $file_actions;
44
45                /*!
46                @function vfs
47                @abstract constructor, sets up variables
48                */
49                function vfs ()
50                {
51                        $this->vfs_shared ();
52                        $this->basedir = $GLOBALS['phpgw_info']['server']['files_dir'];
53                        $this->working_id = $GLOBALS['phpgw_info']['user']['account_id'];
54                        $this->working_lid = $GLOBALS['phpgw']->accounts->id2name($this->working_id);
55                        $this->my_home = $this->fakebase.'/'.$this->working_lid;
56                        $this->now = date ('Y-m-d H:i:s');
57
58                        /*
59                           File/dir attributes, each corresponding to a database field.  Useful for use in loops
60                           If an attribute was added to the table, add it here and possibly add it to
61                           set_attributes ()
62
63                           set_attributes now uses this array().   07-Dec-01 skeeter
64                        */
65
66                        $this->attributes[] = 'deleteable';
67                        $this->attributes[] = 'content';
68                        $this->attributes[] = 'type';
69
70                        /*
71                           Decide whether to use any actual filesystem calls (fopen(), fread(),
72                           unlink(), rmdir(), touch(), etc.).  If not, then we're working completely
73                           in the database.
74                        */
75                        $this->file_actions = $GLOBALS['phpgw_info']['server']['file_store_contents'] == 'filesystem' ||
76                                !$GLOBALS['phpgw_info']['server']['file_store_contents'];
77
78                        // test if the files-dir is inside the document-root, and refuse working if so
79                        //
80                        if ($this->file_actions && $this->in_docroot($this->basedir))
81                        {
82                                $GLOBALS['phpgw']->common->phpgw_header();
83                                if ($GLOBALS['phpgw_info']['flags']['noheader'])
84                                {
85                                        echo parse_navbar();
86                                }
87                                echo '<p align="center"><font color="red"><b>'.lang('Path to user and group files HAS TO BE OUTSIDE of the webservers document-root!!!')."</b></font></p>\n";
88                                $GLOBALS['phpgw']->common->phpgw_exit();
89                        }
90                        /*
91                           These are stored in the MIME-type field and should normally be ignored.
92                           Adding a type here will ensure it is normally ignored, but you will have to
93                           explicitly add it to acl_check (), and to any other SELECT's in this file
94                        */
95
96                        $this->meta_types = array ('journal', 'journal-deleted');
97
98                        /* We store the linked directories in an array now, so we don't have to make the SQL call again */
99                        if ($GLOBALS['phpgw_info']['server']['db_type']=='mssql'
100                                || $GLOBALS['phpgw_info']['server']['db_type']=='sybase')
101                        {
102                                $query = $GLOBALS['phpgw']->db->query ("SELECT directory, name, link_directory, link_name FROM phpgw_vfs WHERE CONVERT(varchar,link_directory) != '' AND CONVERT(varchar,link_name) != ''" . $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__,__FILE__);
103                        }
104                        else
105                        {
106                                $query = $GLOBALS['phpgw']->db->query ("SELECT directory, name, link_directory, link_name FROM phpgw_vfs WHERE (link_directory IS NOT NULL or link_directory != '') AND (link_name IS NOT NULL or link_name != '')" . $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__,__FILE__);
107                        }
108
109                        $this->linked_dirs = array ();
110                        while ($GLOBALS['phpgw']->db->next_record ())
111                        {
112                                $this->linked_dirs[] = $GLOBALS['phpgw']->db->Record;
113                        }
114                }
115
116                /*!
117                @function in_docroot
118                @abstract test if $path lies within the webservers document-root
119                */
120                function in_docroot($path)
121                {
122                        $docroots = array(PHPGW_SERVER_ROOT,$_SERVER['DOCUMENT_ROOT']);
123
124                        foreach ($docroots as $docroot)
125                        {
126                                $len = strlen($docroot);
127
128                                if ($docroot == substr($path,0,$len))
129                                {
130                                        $rest = substr($path,$len);
131
132                                        if (!strlen($rest) || $rest[0] == DIRECTORY_SEPARATOR)
133                                        {
134                                                return True;
135                                        }
136                                }
137                        }
138                        return False;
139                }
140
141                /*!
142                @function extra_sql
143                @abstract Return extra SQL code that should be appended to certain queries
144                @param query_type The type of query to get extra SQL code for, in the form of a VFS_SQL define
145                @result Extra SQL code
146                */
147                function extra_sql ($data)
148                {
149                        if (!is_array ($data))
150                        {
151                                $data = array ('query_type' => VFS_SQL_SELECT);
152                        }
153
154                        if ($data['query_type'] == VFS_SQL_SELECT || $data['query_type'] == VFS_SQL_DELETE || $data['query_type'] = VFS_SQL_UPDATE)
155                        {
156                                $sql = ' AND ((';
157
158                                foreach ($this->meta_types as $num => $type)
159                                {
160                                        if ($num)
161                                                $sql .= ' AND ';
162
163                                        $sql .= "mime_type != '$type'";
164                                }
165
166                                $sql .= ') OR mime_type IS NULL)';
167                        }
168
169                        return ($sql);
170                }
171
172                /*!
173                @function add_journal
174                @abstract Add a journal entry after (or before) completing an operation,
175                          and increment the version number.  This function should be used internally only
176                @discussion Note that state_one and state_two are ignored for some VFS_OPERATION's, for others
177                            they are required.  They are ignored for any "custom" operation
178                            The two operations that require state_two:
179                            operation                   state_two
180                            VFS_OPERATION_COPIED        fake_full_path of copied to
181                            VFS_OPERATION_MOVED         fake_full_path of moved to
182
183                            If deleting, you must call add_journal () before you delete the entry from the database
184                @param string File or directory to add entry for
185                @param relatives Relativity array
186                @param operation The operation that was performed.  Either a VFS_OPERATION define or
187                                  a non-integer descriptive text string
188                @param state_one The first "state" of the file or directory.  Can be a file name, size,
189                                  location, whatever is appropriate for the specific operation
190                @param state_two The second "state" of the file or directory
191                @param incversion Boolean True/False.  Increment the version for the file?  Note that this is
192                                   handled automatically for the VFS_OPERATION defines.
193                                   i.e. VFS_OPERATION_EDITED would increment the version, VFS_OPERATION_COPIED
194                                   would not
195                @result Boolean True/False
196                */
197                function add_journal ($data)
198                {
199                        if (!is_array ($data))
200                        {
201                                $data = array ();
202                        }
203
204                        $default_values = array
205                                (
206                                        'relatives'     => array (RELATIVE_CURRENT),
207                                        'state_one'     => False,
208                                        'state_two'     => False,
209                                        'incversion'    => True
210                                );
211
212                        $data = array_merge ($this->default_values ($data, $default_values), $data);
213
214                        $account_id = $GLOBALS['phpgw_info']['user']['account_id'];
215
216                        $p = $this->path_parts (array ('string' => $data['string'], 'relatives' => array ($data['relatives'][0])));
217
218                        /* We check that they have some sort of access to the file other than read */
219                        if (!$this->acl_check (array ('string' => $p->fake_full_path, 'relatives' => array ($p->mask), 'operation' => PHPGW_ACL_WRITE)) &&
220                                !$this->acl_check (array ('string' => $p->fake_full_path, 'relatives' => array ($p->mask), 'operation' => PHPGW_ACL_EDIT)) &&
221                                !$this->acl_check (array ('string' => $p->fake_full_path, 'relatives' => array ($p->mask), 'operation' => PHPGW_ACL_DELETE)))
222                        {
223                                return False;
224                        }
225
226                        if (!$this->file_exists (array ('string' => $p->fake_full_path, 'relatives' => array ($p->mask))))
227                        {
228                                return False;
229                        }
230
231                        $ls_array = $this->ls (array (
232                                        'string' => $p->fake_full_path,
233                                        'relatives' => array ($p->mask),
234                                        'checksubdirs' => False,
235                                        'mime_type'     => False,
236                                        'nofiles'       => True
237                                )
238                        );
239                        $file_array = $ls_array[0];
240
241                        $sql = 'INSERT INTO phpgw_vfs (';
242                        $sql2 .= ' VALUES (';
243
244                        for ($i = 0; list ($attribute, $value) = each ($file_array); $i++)
245                        {
246                                if ($attribute == 'file_id' || $attribute == 'content')
247                                {
248                                        continue;
249                                }
250
251                                if ($attribute == 'owner_id')
252                                {
253                                        $value = $account_id;
254                                }
255
256                                if ($attribute == 'created')
257                                {
258                                        $value = $this->now;
259                                }
260
261                                if ($attribute == 'modified' && !$modified)
262                                {
263                                        unset ($value);
264                                }
265
266                                if ($attribute == 'mime_type')
267                                {
268                                        $value = 'journal';
269                                }
270                                if ($attribute == 'summary')
271                                {
272                                        $value = '';
273                                }
274
275                                if ($attribute == 'comment')
276                                {
277                                        switch ($data['operation'])
278                                        {
279                                                case VFS_OPERATION_CREATED:
280                                                        $value = 'Created';
281                                                        $data['incversion'] = True;
282                                                        break;
283                                                case VFS_OPERATION_EDITED:
284                                                        $value = 'Edited';
285                                                        $data['incversion'] = True;
286                                                        break;
287                                                case VFS_OPERATION_EDITED_COMMENT:
288                                                        $value = 'Edited comment';
289                                                        $data['incversion'] = False;
290                                                        break;
291                                                case VFS_OPERATION_COPIED:
292                                                        if (!$data['state_one'])
293                                                        {
294                                                                $data['state_one'] = $p->fake_full_path;
295                                                        }
296                                                        if (!$data['state_two'])
297                                                        {
298                                                                return False;
299                                                        }
300                                                        $value = 'Copied '.$data['state_one'].' to '.$data['state_two'];
301                                                        $data['incversion'] = False;
302                                                        break;
303                                                case VFS_OPERATION_MOVED:
304                                                        if (!$data['state_one'])
305                                                        {
306                                                                $data['state_one'] = $p->fake_full_path;
307                                                        }
308                                                        if (!$data['state_two'])
309                                                        {
310                                                                return False;
311                                                        }
312                                                        $value = 'Moved '.$data['state_one'].' to '.$data['state_two'];
313                                                        $data['incversion'] = False;
314                                                        break;
315                                                case VFS_OPERATION_DELETED:
316                                                        $value = 'Deleted';
317                                                        $data['incversion'] = False;
318                                                        break;
319                                                default:
320                                                        $value = $data['operation'];
321                                                        break;
322                                        }
323                                }
324
325                                /*
326                                   Let's increment the version for the file itself.  We keep the current
327                                   version when making the journal entry, because that was the version that
328                                   was operated on.  The maximum numbers for each part in the version string:
329                                   none.99.9.9
330                                */
331                                if ($attribute == 'version' && $data['incversion'])
332                                {
333                                        $version_parts = split ("\.", $value);
334                                        $newnumofparts = $numofparts = count ($version_parts);
335
336                                        if ($version_parts[3] >= 9)
337                                        {
338                                                $version_parts[3] = 0;
339                                                $version_parts[2]++;
340                                                $version_parts_3_update = 1;
341                                        }
342                                        elseif (isset ($version_parts[3]))
343                                        {
344                                                $version_parts[3]++;
345                                        }
346
347                                        if ($version_parts[2] >= 9 && $version_parts[3] == 0 && $version_parts_3_update)
348                                        {
349                                                $version_parts[2] = 0;
350                                                $version_parts[1]++;
351                                        }
352
353                                        if ($version_parts[1] > 99)
354                                        {
355                                                $version_parts[1] = 0;
356                                                $version_parts[0]++;
357                                        }
358
359                                        for ($i = 0; $i < $newnumofparts; $i++)
360                                        {
361                                                if (!isset ($version_parts[$i]))
362                                                {
363                                                        break;
364                                                }
365
366                                                if ($i)
367                                                {
368                                                        $newversion .= '.';
369                                                }
370
371                                                $newversion .= $version_parts[$i];
372                                        }
373
374                                        $this->set_attributes (array(
375                                                        'string'        => $p->fake_full_path,
376                                                        'relatives'     => array ($p->mask),
377                                                        'attributes'    => array(
378                                                                                'version' => $newversion
379                                                                        )
380                                                )
381                                        );
382                                }
383
384                                if (isset ($value))
385                                {
386                                        if ($i > 1)
387                                        {
388                                                $sql .= ', ';
389                                                $sql2 .= ', ';
390                                        }
391
392                                        $sql .= "$attribute";
393                                        $sql2 .= "'" . $this->clean_string (array ('string' => $value)) . "'";
394                                }
395                        }
396
397                        $sql .= ')';
398                        $sql2 .= ')';
399
400                        $sql .= $sql2;
401
402                        /*
403                           These are some special situations where we need to flush the journal entries
404                           or move the 'journal' entries to 'journal-deleted'.  Kind of hackish, but they
405                           provide a consistent feel to the system
406                        */
407                        if ($data['operation'] == VFS_OPERATION_CREATED)
408                        {
409                                $flush_path = $p->fake_full_path;
410                                $deleteall = True;
411                        }
412
413                        if ($data['operation'] == VFS_OPERATION_COPIED || $data['operation'] == VFS_OPERATION_MOVED)
414                        {
415                                $flush_path = $data['state_two'];
416                                $deleteall = False;
417                        }
418
419                        if ($flush_path)
420                        {
421                                $flush_path_parts = $this->path_parts (array(
422                                                'string'        => $flush_path,
423                                                'relatives'     => array (RELATIVE_NONE)
424                                        )
425                                );
426
427                                $this->flush_journal (array(
428                                                'string'        => $flush_path_parts->fake_full_path,
429                                                'relatives'     => array ($flush_path_parts->mask),
430                                                'deleteall'     => $deleteall
431                                        )
432                                );
433                        }
434
435                        if ($data['operation'] == VFS_OPERATION_COPIED)
436                        {
437                                /*
438                                   We copy it going the other way as well, so both files show the operation.
439                                   The code is a bad hack to prevent recursion.  Ideally it would use VFS_OPERATION_COPIED
440                                */
441                                $this->add_journal (array(
442                                                'string'        => $data['state_two'],
443                                                'relatives'     => array (RELATIVE_NONE),
444                                                'operation'     => 'Copied '.$data['state_one'].' to '.$data['state_two'],
445                                                'state_one'     => NULL,
446                                                'state_two'     => NULL,
447                                                'incversion'    => False
448                                        )
449                                );
450                        }
451
452                        if ($data['operation'] == VFS_OPERATION_MOVED)
453                        {
454                                $state_one_path_parts = $this->path_parts (array(
455                                                'string'        => $data['state_one'],
456                                                'relatives'     => array (RELATIVE_NONE)
457                                        )
458                                );
459
460                                $query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET mime_type='journal-deleted' WHERE directory='".
461                                        $GLOBALS['phpgw']->db->db_addslashes($state_one_path_parts->fake_leading_dirs_clean)."' AND name='".
462                                        $GLOBALS['phpgw']->db->db_addslashes($state_one_path_parts->fake_name_clean)."' AND mime_type='journal'");
463
464                                /*
465                                   We create the file in addition to logging the MOVED operation.  This is an
466                                   advantage because we can now search for 'Create' to see when a file was created
467                                */
468                                $this->add_journal (array(
469                                                'string'        => $data['state_two'],
470                                                'relatives'     => array (RELATIVE_NONE),
471                                                'operation'     => VFS_OPERATION_CREATED
472                                        )
473                                );
474                        }
475
476                        /* This is the SQL query we made for THIS request, remember that one? */
477                        $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
478
479                        /*
480                           If we were to add an option of whether to keep journal entries for deleted files
481                           or not, it would go in the if here
482                        */
483                        if ($data['operation'] == VFS_OPERATION_DELETED)
484                        {
485                                $query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET mime_type='journal-deleted' WHERE directory='".
486                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
487                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."' AND mime_type='journal'");
488                        }
489
490                        return True;
491                }
492
493                /*!
494                @function flush_journal
495                @abstract Flush journal entries for $string.  Used before adding $string
496                @discussion flush_journal () is an internal function and should be called from add_journal () only
497                @param string File/directory to flush journal entries of
498                @param relatives Realtivity array
499                @param deleteall Delete all types of journal entries, including the active Create entry.
500                                  Normally you only want to delete the Create entry when replacing the file
501                                  Note that this option does not effect $deleteonly
502                @param deletedonly Only flush 'journal-deleted' entries (created when $string was deleted)
503                @result Boolean True/False
504                */
505                function flush_journal ($data)
506                {
507                        if (!is_array ($data))
508                        {
509                                $data = array ();
510                        }
511
512                        $default_values = array
513                                (
514                                        'relatives'     => array (RELATIVE_CURRENT),
515                                        'deleteall'     => False,
516                                        'deletedonly'   => False
517                                );
518
519                        $data = array_merge ($this->default_values ($data, $default_values), $data);
520
521                        $p = $this->path_parts (array(
522                                        'string'        => $data['string'],
523                                        'relatives'     => array ($data['relatives'][0])
524                                )
525                        );
526
527
528                        $sql = "DELETE FROM phpgw_vfs WHERE directory='".
529                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean).SEP
530                                .$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'";
531
532                        if (!$data['deleteall'])
533                        {
534                                $sql .= " AND (mime_type != 'journal' AND comment != 'Created')";
535                        }
536
537                        $sql .= "  AND (mime_type='journal-deleted'";
538
539                        if (!$data['deletedonly'])
540                        {
541                                $sql .= " OR mime_type='journal'";
542                        }
543
544                        $sql .= ")";
545                        $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
546
547                        if ($query)
548                        {
549                                return True;
550                        }
551                        else
552                        {
553                                return False;
554                        }
555                }
556
557                /*
558                 * See vfs_shared
559                 */
560                function get_journal ($data)
561                {
562                        if (!is_array ($data))
563                        {
564                                $data = array ();
565                        }
566
567                        $default_values = array
568                                (
569                                        'relatives'     => array (RELATIVE_CURRENT),
570                                        'type'  => False
571                                );
572
573                        $data = array_merge ($this->default_values ($data, $default_values), $data);
574
575                        $p = $this->path_parts (array(
576                                        'string'        => $data['string'],
577                                        'relatives'     => array ($data['relatives'][0])
578                                )
579                        );
580
581                        if (!$this->acl_check (array(
582                                        'string' => $p->fake_full_path,
583                                        'relatives' => array ($p->mask)
584                                )))
585                        {
586                                return False;
587                        }
588
589                        $sql = "SELECT * FROM phpgw_vfs WHERE directory='".
590                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
591                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'";
592
593                        if ($data['type'] == 1)
594                        {
595                                $sql .= " AND mime_type='journal'";
596                        }
597                        elseif ($data['type'] == 2)
598                        {
599                                $sql .= " AND mime_type='journal-deleted'";
600                        }
601                        else
602                        {
603                                $sql .= " AND (mime_type='journal' OR mime_type='journal-deleted')";
604                        }
605
606                        $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
607
608                        while ($GLOBALS['phpgw']->db->next_record ())
609                        {
610                                $rarray[] = $GLOBALS['phpgw']->db->Record;
611                        }
612
613                        return $rarray;
614                }
615
616                /*
617                 * See vfs_shared
618                 */
619                function acl_check ($data)
620                {
621
622                        if (!is_array ($data))
623                        {
624                                $data = array ();
625                        }
626       
627                        $default_values = array
628                                (
629                                        'relatives'     => array (RELATIVE_CURRENT),
630                                        'operation'     => PHPGW_ACL_READ,
631                                        'must_exist'    => False
632                                );
633
634                        $data = array_merge ($this->default_values ($data, $default_values), $data);
635
636                        /* Accommodate special situations */
637                        if ($this->override_acl || $data['relatives'][0] == RELATIVE_USER_APP)
638                        {
639                                return True;
640                        }
641
642                        /* ExpressoLivre principle: In your home you do what you want*/
643                        if (strpos($data['string'],$this->my_home) === 0)
644                                return True;
645                        if ($data['relatives'][0] == RELATIVE_NONE || $data['relatives'][0] == RELATIVE_ALL)
646                        {
647                                $path = explode('/',$data['string']);
648                                $data['string'] = '/'.$path[1].'/'.$path[2];
649                        }
650
651
652
653                        if (!$data['owner_id'])
654                        {
655                                $p = $this->path_parts (array(
656                                                'string'        => $data['string'],
657                                                'relatives'     => array ($data['relatives'][0])
658                                        )
659                                );
660
661                                /* Temporary, until we get symlink type files set up */
662                                if ($p->outside)
663                                {
664                                        return True;
665                                }
666
667                                /* Read access is always allowed here, but nothing else is */
668                                if ($data['string'] == '/' || $data['string'] == $this->fakebase)
669                                {
670                                        if ($data['operation'] == PHPGW_ACL_READ)
671                                        {
672                                                return True;
673                                        }
674                                        else
675                                        {
676                                                return False;
677                                        }
678                                }
679
680                                /* If the file doesn't exist, we get ownership from the parent directory */
681                                if (!$this->file_exists (array(
682                                                'string'        => $p->fake_full_path,
683                                                'relatives'     => array ($p->mask)
684                                        ))
685                                )
686                                {
687                                        if ($data['must_exist'])
688                                        {
689                                                return False;
690                                        }
691
692                                        $data['string'] = $p->fake_leading_dirs;
693                                        $p2 = $this->path_parts (array(
694                                                        'string'        => $data['string'],
695                                                        'relatives'     => array ($p->mask)
696                                                )
697                                        );
698
699                                        if (!$this->file_exists (array(
700                                                        'string'        => $data['string'],
701                                                        'relatives'     => array ($p->mask)
702                                                ))
703                                        )
704                                        {
705                                                return False;
706                                        }
707                                }
708                                else
709                                {
710                                        $p2 = $p;
711                                }
712
713                                /*
714                                   We don't use ls () to get owner_id as we normally would,
715                                   because ls () calls acl_check (), which would create an infinite loop
716                                 */
717                                $owner_id = $this->ownerOf($p2->fake_leading_dirs_clean,$p2->fake_name_clean);
718                        }
719                        else
720                        {
721                                $owner_id = $data['owner_id'];
722                        }
723
724                        $user_id = $GLOBALS['phpgw_info']['user']['account_id'];
725
726                        /* They always have access to their own files */
727                        if ($owner_id == $user_id)
728                        {
729                                return True;
730                        }
731
732                        /* Check if they're in the group */
733                        $memberships = $GLOBALS['phpgw']->accounts->membership ($user_id);
734
735                        if (is_array ($memberships))
736                        {
737                                foreach ($memberships as $group_array)
738                                {
739                                        if ($owner_id == $group_array['account_id'])
740                                        {
741                                                $group_ok = 1;
742                                                break;
743                                        }
744                                }
745                        }
746
747                        $acl = CreateObject ('phpgwapi.acl', $owner_id);
748                        $acl->account_id = $owner_id;
749                        $acl->read_repository ();
750
751                        $rights = $acl->get_rights ($user_id);
752
753                        /* Add privileges from the groups this user belongs to */
754                        if (is_array ($memberships))
755                        {
756                                foreach ($memberships as $group_array)
757                                {
758                                        $rights |= $acl->get_rights ($group_array['account_id']);
759                                }
760                        }
761
762                        if ($rights & $data['operation'])
763                        {
764                                return True;
765                        }
766                        elseif (!$rights && $group_ok)
767                        {
768                                $conf = CreateObject('phpgwapi.config', 'phpgwapi');
769                                $conf->read_repository();
770                                if ($conf->config_data['acl_default'] == 'grant')
771                                {
772                                        return True;
773                                }
774                                else
775                                {
776                                        return False;
777                                }
778                        }
779                        else
780                        {
781                                return False;
782                        }
783                }
784                function ownerOf($base,$path){
785                        $query = $GLOBALS['phpgw']->db->query ("SELECT owner_id FROM phpgw_vfs WHERE directory='".
786                        $GLOBALS['phpgw']->db->db_addslashes($base)."' AND name='".
787                        $GLOBALS['phpgw']->db->db_addslashes($path)."' ".$this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
788                        $GLOBALS['phpgw']->db->next_record();
789                        $owner_id = $GLOBALS['phpgw']->db->Record['owner_id'];
790                        if (!$owner_id)
791                        {
792                                $owner_id = 0;
793                        }
794                        return $owner_id;
795                }
796
797                /*used to safe memory in downloads*/
798                function print_content ($data)
799                {
800                        if (!is_array ($data))
801                        {
802                                $data = array ();
803                        }
804
805                        $default_values = array
806                                (
807                                        'relatives'     => array (RELATIVE_CURRENT)
808                                );
809
810                        $data = array_merge ($this->default_values ($data, $default_values), $data);
811
812                        $p = $this->path_parts (array(
813                                        'string'        => $data['string'],
814                                        'relatives'     => array ($data['relatives'][0])
815                                )
816                        );
817
818                        if (!$this->acl_check (array(
819                                        'string'        => $p->fake_full_path,
820                                        'relatives'     => array ($p->mask),
821                                        'operation'     => PHPGW_ACL_READ
822                                ))
823                        )
824                        {
825                                return False;
826                        }
827                        session_write_close();
828                                if ($fp = fopen ($p->real_full_path, 'rb'))
829                                {
830                                        for ($i=0; $i<=filesize($p->real_full_path); $i+=10240)
831                                        {
832                                                echo fread($fp, $i);
833                                                flush();
834                                                usleep(50);
835                                        }
836                                        fclose ($fp);
837                                }
838                                else
839                                {
840                                        return False;
841                                }
842                        return True;
843                }
844
845                /*
846                 * See vfs_shared
847                 */
848                function read ($data)
849                {
850                        if (!is_array ($data))
851                        {
852                                $data = array ();
853                        }
854
855                        $default_values = array
856                                (
857                                        'relatives'     => array (RELATIVE_CURRENT)
858                                );
859
860                        $data = array_merge ($this->default_values ($data, $default_values), $data);
861
862                        $p = $this->path_parts (array(
863                                        'string'        => $data['string'],
864                                        'relatives'     => array ($data['relatives'][0])
865                                )
866                        );
867
868                        if (!$this->acl_check (array(
869                                        'string'        => $p->fake_full_path,
870                                        'relatives'     => array ($p->mask),
871                                        'operation'     => PHPGW_ACL_READ
872                                ))
873                        )
874                        {
875                                return False;
876                        }
877
878                        $conf = CreateObject('phpgwapi.config', 'phpgwapi');
879                        $conf->read_repository();
880                        if ($this->file_actions || $p->outside)
881                        {
882                                if ($fp = fopen ($p->real_full_path, 'rb'))
883                                {
884                                        $contents = fread ($fp, filesize ($p->real_full_path));
885                                        fclose ($fp);
886                                }
887                                else
888                                {
889                                        $contents = False;
890                                }
891                        }
892                        else
893                        {
894                                $ls_array = $this->ls (array(
895                                                'string'        => $p->fake_full_path,
896                                                'relatives'     => array ($p->mask),
897                                        )
898                                );
899
900                                $contents = $ls_array[0]['content'];
901                        }
902
903                        return $contents;
904                }
905
906                /*
907                 * See vfs_shared
908                 */
909                function write ($data)
910                {
911                        if (!is_array ($data))
912                        {
913                                $data = array ();
914                        }
915
916                        $path = explode('/',$data['string']);
917                        $quota = $this->get_quota(array('string' => '/'.$path[1].'/'.$path[2]));
918                        if ($quota > 0 && $this->get_size('/'.$path[1].'/'.$path[2]) >= $quota * 1024 * 1024)
919                                return false;
920
921
922                        $default_values = array
923                                (
924                                        'relatives'     => array (RELATIVE_CURRENT),
925                                        'content'       => ''
926                                );
927
928                        $data = array_merge ($this->default_values ($data, $default_values), $data);
929
930                        $p = $this->path_parts (array(
931                                        'string'        => $data['string'],
932                                        'relatives'     => array ($data['relatives'][0])
933                                )
934                        );
935
936                        if ($this->file_exists (array (
937                                        'string'        => $p->fake_full_path,
938                                        'relatives'     => array ($p->mask)
939                                ))
940                        )
941                        {
942                                $acl_operation = PHPGW_ACL_EDIT;
943                                $journal_operation = VFS_OPERATION_EDITED;
944                        }
945                        else
946                        {
947                                $acl_operation = PHPGW_ACL_ADD;
948                        }
949                        umask(0177);
950
951                        /*
952                           If 'string' doesn't exist, touch () creates both the file and the database entry
953                           If 'string' does exist, touch () sets the modification time and modified by
954                        */
955                        $this->touch (array(
956                                        'string'        => $p->fake_full_path,
957                                        'relatives'     => array ($p->mask)
958                                )
959                        );
960
961                        $conf = CreateObject('phpgwapi.config', 'phpgwapi');
962                        $conf->read_repository();
963                        if ($this->file_actions)
964                        {
965                                if ($fp = fopen ($p->real_full_path, 'wb'))
966                                {
967                                        fwrite ($fp, $data['content']);
968                                        fclose ($fp);
969                                        $write_ok = 1;
970                                }
971                        }
972
973                        if ($write_ok || !$this->file_actions)
974                        {
975                                if ($this->file_actions)
976                                {
977                                        $set_attributes_array = array(
978                                                'size' => filesize ($p->real_full_path)
979                                        );
980                                }
981                                else
982                                {
983                                        $set_attributes_array = array (
984                                                'size'  => strlen ($data['content']),
985                                                'content'       => $data['content']
986                                        );
987                                }
988
989
990                                $this->set_attributes (array
991                                        (
992                                                'string'        => $p->fake_full_path,
993                                                'relatives'     => array ($p->mask),
994                                                'attributes'    => $set_attributes_array
995                                        )
996                                );
997
998                                if ($journal_operation)
999                                {
1000                                        $this->add_journal (array(
1001                                                        'string'        => $p->fake_full_path,
1002                                                        'relatives'     => array ($p->mask),
1003                                                        'operation'     => $journal_operation
1004                                                )
1005                                        );
1006                                }
1007
1008                                return True;
1009                        }
1010                        else
1011                        {
1012                                return False;
1013                        }
1014                }
1015
1016                /*
1017                 * See vfs_shared
1018                 */
1019                function touch ($data)
1020                {
1021                        if (!is_array ($data))
1022                        {
1023                                $data = array ();
1024                        }
1025
1026                        $default_values = array
1027                                (
1028                                        'relatives'     => array (RELATIVE_CURRENT)
1029                                );
1030
1031                        $data = array_merge ($this->default_values ($data, $default_values), $data);
1032
1033                        $account_id = $GLOBALS['phpgw_info']['user']['account_id'];
1034                        $currentapp = $GLOBALS['phpgw_info']['flags']['currentapp'];
1035
1036                        $p = $this->path_parts (array(
1037                                        'string'        => $data['string'],
1038                                        'relatives'     => array ($data['relatives'][0])
1039                                )
1040                        );
1041
1042                        umask (0177);
1043
1044                        if ($this->file_actions)
1045                        {
1046                                /*
1047                                   PHP's touch function will automatically decide whether to
1048                                   create the file or set the modification time
1049                                */
1050                                $rr = @touch ($p->real_full_path);
1051
1052                                if ($p->outside)
1053                                {
1054                                        return $rr;
1055                                }
1056                        }
1057
1058                        /* We, however, have to decide this ourselves */
1059                        if ($this->file_exists (array(
1060                                        'string'        => $p->fake_full_path,
1061                                        'relatives'     => array ($p->mask)
1062                                ))
1063                        )
1064                        {
1065                                if (!$this->acl_check (array(
1066                                                'string'        => $p->fake_full_path,
1067                                                'relatives'     => array ($p->mask),
1068                                                'operation'     => PHPGW_ACL_EDIT
1069                                        )))
1070                                {
1071                                        return False;
1072                                }
1073
1074                                $vr = $this->set_attributes (array(
1075                                                'string'        => $p->fake_full_path,
1076                                                'relatives'     => array ($p->mask),
1077                                                'attributes'    => array(
1078                                                                        'modifiedby_id' => $account_id,
1079                                                                        'modified' => $this->now
1080                                                                )
1081                                                )
1082                                        );
1083                        }
1084                        else
1085                        {
1086                                if (!$this->acl_check (array(
1087                                                'string'        => $p->fake_full_path,
1088                                                'relatives'     => array ($p->mask),
1089                                                'operation'     => PHPGW_ACL_ADD
1090                                        ))
1091                                )
1092                                {
1093                                        return False;
1094                                }
1095
1096                                $query = $GLOBALS['phpgw']->db->query ("INSERT INTO phpgw_vfs (owner_id, directory, name) VALUES ($this->working_id, '".
1097                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."', '".
1098                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."')", __LINE__, __FILE__);
1099
1100                                $this->set_attributes(array(
1101                                        'string'        => $p->fake_full_path,
1102                                        'relatives'     => array ($p->mask),
1103                                        'attributes'    => array (
1104                                                                'createdby_id' => $account_id,
1105                                                                'created' => $this->now,
1106                                                                'size' => 0,
1107                                                                'deleteable' => 'Y',
1108                                                                'app' => $currentapp
1109                                                        )
1110                                        )
1111                                );
1112                                $this->correct_attributes (array(
1113                                                'string'        => $p->fake_full_path,
1114                                                'relatives'     => array ($p->mask)
1115                                        )
1116                                );
1117       
1118                                $this->add_journal (array(
1119                                                'string'        => $p->fake_full_path,
1120                                                'relatives'     => array ($p->mask),
1121                                                'operation'     => VFS_OPERATION_CREATED
1122                                        )
1123                                );
1124                        }
1125
1126                        if ($rr || $vr || $query)
1127                        {
1128                                return True;
1129                        }
1130                        else
1131                        {
1132                                return False;
1133                        }
1134                }
1135
1136                /*
1137                 * See vfs_shared
1138                 * If $data['symlink'] the file is symlinked instead of copied
1139                 */
1140                function cp ($data)
1141                {
1142                        if (!is_array ($data))
1143                        {
1144                                $data = array ();
1145                        }
1146                        if ($data['relatives'][1] == RELATIVE_NONE)
1147                                $path = explode(SEP,$data['to']);
1148                        else
1149                                $path = explode(SEP,$this->my_home);
1150                        $quota = $this->get_quota(array('string' => SEP.$path[1].SEP.$path[2]));
1151                        $size = $this->get_size(array('string' => SEP.$path[1].SEP.$path[2], 'relatives' => $data['relatives'][1]));
1152
1153                        if ($quota > 0 && ($quota * 1024 * 1024) < $size)
1154                                return false;
1155
1156                        $default_values = array
1157                                (
1158                                        'relatives'     => array (RELATIVE_CURRENT, RELATIVE_CURRENT)
1159                                );
1160
1161                        $data = array_merge ($this->default_values ($data, $default_values), $data);
1162
1163                        $account_id = $GLOBALS['phpgw_info']['user']['account_id'];
1164
1165                        $f = $this->path_parts (array(
1166                                        'string'        => $data['from'],
1167                                        'relatives'     => array ($data['relatives'][0])
1168                                )
1169                        );
1170
1171                        $t = $this->path_parts (array(
1172                                        'string'        => $data['to'],
1173                                        'relatives'     => array ($data['relatives'][1])
1174                                )
1175                        );
1176
1177                        if (!$this->acl_check (array(
1178                                        'string'        => $f->fake_full_path,
1179                                        'relatives'     => array ($f->mask),
1180                                        'operation'     => PHPGW_ACL_READ
1181                                ))
1182                        )
1183                        {
1184                                return False;
1185                        }
1186
1187                        if ($exists = $this->file_exists (array(
1188                                        'string'        => $t->fake_full_path,
1189                                        'relatives'     => array ($t->mask)
1190                                ))
1191                        )
1192                        {
1193                                if (!$this->acl_check (array(
1194                                                'string'        => $t->fake_full_path,
1195                                                'relatives'     => array ($t->mask),
1196                                                'operation'     => PHPGW_ACL_EDIT
1197                                        ))
1198                                )
1199                                {
1200                                        return False;
1201                                }
1202                        }
1203                        else
1204                        {
1205                                if (!$this->acl_check (array(
1206                                                'string'        => $t->fake_full_path,
1207                                                'relatives'     => array ($t->mask),
1208                                                'operation'     => PHPGW_ACL_ADD
1209                                        ))
1210                                )
1211                                {
1212                                        return False;
1213                                }
1214                        }
1215
1216                        umask(0177);
1217
1218                        if ($this->file_type (array(
1219                                        'string'        => $f->fake_full_path,
1220                                        'relatives'     => array ($f->mask)
1221                                )) != 'Directory'
1222                        )
1223                        {
1224                                if ($this->file_actions)
1225                                {
1226                                        if (@$data['symlink'])
1227                                        {
1228                                                if ($exists)
1229                                                {
1230                                                        @unlink($t->real_full_path);
1231                                                }
1232                                                if (!symlink($f->real_full_path, $t->real_full_path))
1233                                                {
1234                                                        return False;
1235                                                }
1236                                        }
1237                                        elseif (!copy ($f->real_full_path, $t->real_full_path))
1238                                        {
1239                                                return False;
1240                                        }
1241
1242                                        $size = filesize ($t->real_full_path);
1243                                }
1244                                else
1245                                {
1246                                        $content = $this->read (array(
1247                                                        'string'        => $f->fake_full_path,
1248                                                        'relatives'     => array ($f->mask)
1249                                                )
1250                                        );
1251
1252                                        $size = strlen ($content);
1253                                }
1254
1255                                if ($t->outside)
1256                                {
1257                                        return True;
1258                                }
1259
1260                                $ls_array = $this->ls (array(
1261                                                'string'        => $f->fake_full_path,
1262                                                'relatives'     => array ($f->mask),
1263                                                'checksubdirs'  => False,
1264                                                'mime_type'     => False,
1265                                                'summary'       => True,
1266                                                'nofiles'       => True
1267                                        )
1268                                );
1269                                $record = $ls_array[0];
1270
1271                                if ($this->file_exists (array(
1272                                                'string'        => $data['to'],
1273                                                'relatives'     => array ($data['relatives'][1])
1274                                        ))
1275                                )
1276                                {
1277                                        $query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET owner_id='$this->working_id', directory='".
1278                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."', name='".
1279                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."' WHERE owner_id='$this->working_id' AND directory='".
1280                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."' AND name='".
1281                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."'" . $this->extra_sql (VFS_SQL_UPDATE), __LINE__, __FILE__);
1282                               
1283                                        $set_attributes_array = array (
1284                                                'createdby_id' => $account_id,
1285                                                'created' => $this->now,
1286                                                'size' => $size,
1287                                                'mime_type' => $record['mime_type'],
1288                                                'deleteable' => $record['deleteable'],
1289                                                'comment' => $record['comment'],
1290                                                'app' => $record['app']
1291                                        );
1292
1293                                        if (!$this->file_actions)
1294                                        {
1295                                                $set_attributes_array['content'] = $content;
1296                                        }
1297
1298                                        $this->set_attributes(array(
1299                                                'string'        => $t->fake_full_path,
1300                                                'relatives'     => array ($t->mask),
1301                                                'attributes'    => $set_attributes_array
1302                                                )
1303                                        );
1304
1305                                        $this->add_journal (array(
1306                                                        'string'        => $t->fake_full_path,
1307                                                        'relatives'     => array ($t->mask),
1308                                                        'operation'     => VFS_OPERATION_EDITED
1309                                                )
1310                                        );
1311                                }
1312                                else
1313                                {
1314                                        $this->touch (array(
1315                                                        'string'        => $t->fake_full_path,
1316                                                        'relatives'     => array ($t->mask)
1317                                                )
1318                                        );
1319
1320                                        $set_attributes_array = array (
1321                                                'createdby_id' => $account_id,
1322                                                'created' => $this->now,
1323                                                'size' => $size,
1324                                                'mime_type' => $record['mime_type'],
1325                                                'deleteable' => $record['deleteable'],
1326                                                'comment' => $record['comment'],
1327                                                'app' => $record['app']
1328                                        );
1329
1330                                        if (!$this->file_actions)
1331                                        {
1332                                                $set_attributes_array['content'] = $content;
1333                                        }
1334
1335                                        $this->set_attributes(array(
1336                                                        'string'        => $t->fake_full_path,
1337                                                        'relatives'     => array ($t->mask),
1338                                                        'attributes'    => $set_attributes_array
1339                                                )
1340                                        );
1341                                        if (!(strpos(strtoupper($record['mime_type']),'IMAGE') === FALSE))
1342                                        {               
1343                                                $this->set_summary(array(
1344                                                        'string'=> $data['to'],
1345                                                        'relatives' => array ($data['relatives'][1]),
1346                                                        'summary'=> $record['summary']
1347                                                ));
1348                                                unset($record['summary']);
1349                                        }
1350                                }
1351                                $this->correct_attributes (array(
1352                                                'string'        => $t->fake_full_path,
1353                                                'relatives'     => array ($t->mask)
1354                                        )
1355                                );
1356                        }
1357                        else    /* It's a directory */
1358                        {
1359                                /* First, make the initial directory */
1360                                $this->mkdir (array(
1361                                                'string'        => $data['to'],
1362                                                'relatives'     => array ($data['relatives'][1])
1363                                        )
1364                                );
1365
1366                                /* Next, we create all the directories below the initial directory */
1367                                foreach($this->ls (array(
1368                                                'string'        => $f->fake_full_path,
1369                                                'relatives'     => array ($f->mask),
1370                                                'checksubdirs'  => True,
1371                                                'mime_type'     => 'Directory'
1372                                        )) as $entry)
1373                                {
1374                                        $newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry['directory']);
1375                                        $this->mkdir (array(
1376                                                        'string'        => $newdir.'/'.$entry['name'],
1377                                                        'relatives'     => array ($t->mask)
1378                                                )
1379                                        );
1380                                }
1381
1382                                /* Lastly, we copy the files over */
1383                                foreach($this->ls (array(
1384                                                'string'        => $f->fake_full_path,
1385                                                'relatives'     => array ($f->mask)
1386                                        )) as $entry)
1387                                {
1388                                        if ($entry['mime_type'] == 'Directory')
1389                                        {
1390                                                continue;
1391                                        }
1392
1393                                        $newdir = ereg_replace ("^$f->fake_full_path", "$t->fake_full_path", $entry['directory']);
1394                                        $this->cp (array(
1395                                                        'from'  => "$entry[directory]/$entry[name]",
1396                                                        'to'    => "$newdir/$entry[name]",
1397                                                        'relatives'     => array ($f->mask, $t->mask)
1398                                                )
1399                                        );
1400                                }
1401                        }
1402
1403                        if (!$f->outside)
1404                        {
1405                                $this->add_journal (array(
1406                                                'string'        => $f->fake_full_path,
1407                                                'relatives'     => array ($f->mask),
1408                                                'operation'     => VFS_OPERATION_COPIED,
1409                                                'state_one'     => NULL,
1410                                                'state_two'     => $t->fake_full_path
1411                                        )
1412                                );
1413                        }
1414
1415                        return True;
1416                }
1417
1418                /*
1419                 * See vfs_shared
1420                 */
1421                function mv ($data)
1422                {
1423                        if (!is_array ($data))
1424                        {
1425                                $data = array ();
1426                        }
1427                        if ($data['relatives'][1] == RELATIVE_NONE)
1428                        {
1429                                $path = explode('/',$data['to']);
1430                                $quota = $this->get_quota(array('string' => '/'.$path[1].'/'.$path[2]));
1431                                $size = $this->get_size(array('string' => '/'.$path[1].'/'.$path[2], 'relatives' => $data['relatives'][1]));
1432                        }
1433                        else
1434                        {
1435                                $quota = $this->get_quota(array('string' => $this->my_home));
1436                                $size = $this->get_size(array('string' => $this->my_home, 'relatives' => $data['relatives'][1]));
1437                        }
1438                        if ($quota > 0 && $size >= $quota * 1024 * 1024)
1439                                return false;
1440
1441
1442                        $default_values = array
1443                                (
1444                                        'relatives'     => array (RELATIVE_CURRENT, RELATIVE_CURRENT)
1445                                );
1446
1447                        $data = array_merge ($this->default_values ($data, $default_values), $data);
1448
1449                        $account_id = $GLOBALS['phpgw_info']['user']['account_id'];
1450
1451                        $f = $this->path_parts (array(
1452                                        'string'        => $data['from'],
1453                                        'relatives'     => array ($data['relatives'][0])
1454                                )
1455                        );
1456
1457                        $t = $this->path_parts (array(
1458                                        'string'        => $data['to'],
1459                                        'relatives'     => array ($data['relatives'][1])
1460                                )
1461                        );
1462
1463                        if (!$this->acl_check (array(
1464                                        'string'        => $data['to'],
1465                                        'relatives'     => array ($t->mask),
1466                                        'operation'     => PHPGW_ACL_ADD
1467                                ))
1468                        )
1469                        {
1470                                return False;
1471                        }
1472
1473                        if ($this->file_exists (array(
1474                                        'string'        => $t->fake_full_path,
1475                                        'relatives'     => array ($t->mask)
1476                                ))
1477                        )
1478                        {
1479                                if (!$this->acl_check (array(
1480                                                'string'        => $data['to'],
1481                                                'relatives'     => array ($t->mask),
1482                                                'operation'     => PHPGW_ACL_EDIT
1483                                        ))
1484                                )
1485                                {
1486                                        return False;
1487                                }
1488                        }
1489
1490                        umask (0177);
1491
1492                        /* We can't move directories into themselves */
1493                        if (($this->file_type (array(
1494                                        'string'        => $f->fake_full_path,
1495                                        'relatives'     => array ($f->mask)
1496                                ) == 'Directory'))
1497                                && ereg ("^$f->fake_full_path", $t->fake_full_path)
1498                        )
1499                        {
1500                                if (($t->fake_full_path == $f->fake_full_path) || substr ($t->fake_full_path, strlen ($f->fake_full_path), 1) == '/')
1501                                {
1502                                        return False;
1503                                }
1504                        }
1505
1506                        if ($this->file_exists (array(
1507                                        'string'        => $f->fake_full_path,
1508                                        'relatives'     => array ($f->mask)
1509                                ))
1510                        )
1511                        {
1512                                /* We get the listing now, because it will change after we update the database */
1513                                $ls = $this->ls (array(
1514                                                'string'        => $f->fake_full_path,
1515                                                'relatives'     => array ($f->mask)
1516                                        )
1517                                );
1518
1519                                if ($this->file_exists (array(
1520                                                'string'        => $t->fake_full_path,
1521                                                'relatives'     => array ($t->mask)
1522                                        ))
1523                                )
1524                                {
1525                                        $this->rm (array(
1526                                                        'string'        => $t->fake_full_path,
1527                                                        'relatives'     => array ($t->mask)
1528                                                )
1529                                        );
1530                                }
1531
1532                                /*
1533                                   We add the journal entry now, before we delete.  This way the mime_type
1534                                   field will be updated to 'journal-deleted' when the file is actually deleted
1535                                */
1536                                if (!$f->outside)
1537                                {
1538                                        $this->add_journal (array(
1539                                                        'string'        => $f->fake_full_path,
1540                                                        'relatives'     => array ($f->mask),
1541                                                        'operation'     => VFS_OPERATION_MOVED,
1542                                                        'state_one'     => $f->fake_full_path,
1543                                                        'state_two'     => $t->fake_full_path
1544                                                )
1545                                        );
1546                                }
1547
1548                                /*
1549                                   If the from file is outside, it won't have a database entry,
1550                                   so we have to touch it and find the size
1551                                */
1552                                if ($f->outside)
1553                                {
1554                                        $size = filesize ($f->real_full_path);
1555
1556                                        $this->touch (array(
1557                                                        'string'        => $t->fake_full_path,
1558                                                        'relatives'     => array ($t->mask)
1559                                                )
1560                                        );
1561                                        $query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET size=$size WHERE directory='".
1562                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."' AND name='".
1563                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."'" . $this->extra_sql (array ('query_type' => VFS_SQL_UPDATE)), __LINE__, __FILE__);
1564                                }
1565                                elseif (!$t->outside)
1566                                {
1567                                        $query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET name='".
1568                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_name_clean)."', directory='".
1569                                                $GLOBALS['phpgw']->db->db_addslashes($t->fake_leading_dirs_clean)."' WHERE directory='".
1570                                                $GLOBALS['phpgw']->db->db_addslashes($f->fake_leading_dirs_clean)."' AND name='".
1571                                                $GLOBALS['phpgw']->db->db_addslashes($f->fake_name_clean)."'" . $this->extra_sql (array ('query_type' => VFS_SQL_UPDATE)), __LINE__, __FILE__);
1572                                }
1573
1574                                $this->set_attributes(array(
1575                                                'string'        => $t->fake_full_path,
1576                                                'relatives'     => array ($t->mask),
1577                                                'attributes'    => array (
1578                                                                        'modifiedby_id' => $account_id,
1579                                                                        'modified' => $this->now
1580                                                                )
1581                                        )
1582                                );
1583
1584                                $this->correct_attributes (array(
1585                                                'string'        => $t->fake_full_path,
1586                                                'relatives'     => array ($t->mask)
1587                                        )
1588                                );
1589
1590                                if ($this->file_actions)
1591                                {
1592                                        $rr = rename ($f->real_full_path, $t->real_full_path);
1593                                }
1594
1595                                /*
1596                                   This removes the original entry from the database
1597                                   The actual file is already deleted because of the rename () above
1598                                */
1599                                if ($t->outside)
1600                                {
1601                                        $this->rm (array(
1602                                                        'string'        => $f->fake_full_path,
1603                                                        'relatives'     => $f->mask
1604                                                )
1605                                        );
1606                                }
1607                        }
1608                        else
1609                        {
1610                                return False;
1611                        }
1612
1613                        if ($this->file_type (array(
1614                                        'string'        => $t->fake_full_path,
1615                                        'relatives'     => array ($t->mask)
1616                                )) == 'Directory'
1617                        )
1618                        {
1619                                /* We got $ls from above, before we renamed the directory */
1620                                foreach ($ls as $entry)
1621                                {
1622                                        $newdir = ereg_replace ("^$f->fake_full_path", $t->fake_full_path, $entry['directory']);
1623                                        $newdir_clean = $this->clean_string (array ('string' => $newdir));
1624
1625                                        $query = $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET directory='".
1626                                                $GLOBALS['phpgw']->db->db_addslashes($newdir_clean)."' WHERE file_id='$entry[file_id]'" .
1627                                                $this->extra_sql (array ('query_type' => VFS_SQL_UPDATE)), __LINE__, __FILE__);
1628                                        $this->correct_attributes (array(
1629                                                        'string'        => "$newdir/$entry[name]",
1630                                                        'relatives'     => array ($t->mask)
1631                                                )
1632                                        );
1633                                }
1634                        }
1635
1636                        $this->add_journal (array(
1637                                        'string'        => $t->fake_full_path,
1638                                        'relatives'     => array ($t->mask),
1639                                        'operation'     => VFS_OPERATION_MOVED,
1640                                        'state_one'     => $f->fake_full_path,
1641                                        'state_two'     => $t->fake_full_path
1642                                )
1643                        );
1644
1645                        return True;
1646                }
1647
1648                /*
1649                 * See vfs_shared
1650                 */
1651                function rm ($data)
1652                {
1653                        if (!is_array ($data))
1654                        {
1655                                $data = array ();
1656                        }
1657
1658                        $default_values = array
1659                                (
1660                                        'relatives'     => array (RELATIVE_CURRENT)
1661                                );
1662
1663                        $data = array_merge ($this->default_values ($data, $default_values), $data);
1664
1665                        $p = $this->path_parts (array(
1666                                        'string'        => $data['string'],
1667                                        'relatives'     => array ($data['relatives'][0])
1668                                )
1669                        );
1670                        if (!$this->file_exists (array(
1671                                        'string'        => $data['string'],
1672                                        'relatives'     => array ($data['relatives'][0])
1673                                ))
1674                        )
1675                        {
1676                                if ($this->file_actions)
1677                                {
1678                                        $rr = unlink ($p->real_full_path);
1679                                }
1680                                else
1681                                {
1682                                        $rr = True;
1683                                }
1684
1685                                if ($rr)
1686                                {
1687                                        return True;
1688                                }
1689                                else
1690                                {
1691                                        return False;
1692                                }
1693                        }
1694
1695                        if ($this->file_type (array(
1696                                        'string'        => $data['string'],
1697                                        'relatives'     => array ($data['relatives'][0])
1698                                )) != 'Directory'
1699                        )
1700                        {
1701                                $this->add_journal (array(
1702                                                'string'        => $p->fake_full_path,
1703                                                'relatives'     => array ($p->mask),
1704                                                'operation'     => VFS_OPERATION_DELETED
1705                                        )
1706                                );
1707
1708                                $query = $GLOBALS['phpgw']->db->query ("DELETE FROM phpgw_vfs WHERE directory='".
1709                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
1710                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'".$this->extra_sql (array ('query_type' => VFS_SQL_DELETE)), __LINE__, __FILE__);
1711
1712                                if ($this->file_actions)
1713                                {
1714                                        $rr = unlink ($p->real_full_path);
1715                                }
1716                                else
1717                                {
1718                                        $rr = True;
1719                                }
1720
1721                                if ($query || $rr)
1722                                {
1723                                        return True;
1724                                }
1725                                else
1726                                {
1727                                        return False;
1728                                }
1729                        }
1730                        else
1731                        {
1732                                $ls = $this->ls (array(
1733                                                'string'        => $p->fake_full_path,
1734                                                'relatives'     => array ($p->mask)
1735                                        )
1736                                );
1737
1738                                /* First, we cycle through the entries and delete the files */
1739                                foreach($ls as $entry)
1740                                {
1741                                        if ($entry['mime_type'] == 'Directory')
1742                                        {
1743                                                continue;
1744                                        }
1745
1746                                        $this->rm (array(
1747                                                        'string'        => "$entry[directory]/$entry[name]",
1748                                                        'relatives'     => array ($p->mask)
1749                                                )
1750                                        );
1751                                }
1752
1753                                /* Now we cycle through again and delete the directories */
1754                                foreach ($ls as $entry)
1755                                {
1756                                        if ($entry['mime_type'] != 'Directory')
1757                                        {
1758                                                continue;
1759                                        }
1760
1761                                        /* Only the best in confusing recursion */
1762                                        $this->rm (array(
1763                                                        'string'        => "$entry[directory]/$entry[name]",
1764                                                        'relatives'     => array ($p->mask)
1765                                                )
1766                                        );
1767                                }
1768
1769                                /* If the directory is linked, we delete the placeholder directory */
1770                                $ls_array = $this->ls (array(
1771                                                'string'        => $p->fake_full_path,
1772                                                'relatives'     => array ($p->mask),
1773                                                'checksubdirs'  => False,
1774                                                'mime_type'     => False,
1775                                                'nofiles'       => True
1776                                        )
1777                                );
1778                                $link_info = $ls_array[0];
1779
1780                                if ($link_info['link_directory'] && $link_info['link_name'])
1781                                {
1782                                        $path = $this->path_parts (array(
1783                                                        'string'        => $link_info['directory'] . '/' . $link_info['name'],
1784                                                        'relatives'     => array ($p->mask),
1785                                                        'nolinks'       => True
1786                                                )
1787                                        );
1788
1789                                        if ($this->file_actions)
1790                                        {
1791                                                rmdir ($path->real_full_path);
1792                                        }
1793                                }
1794
1795                                /* Last, we delete the directory itself */
1796                                $this->add_journal (array(
1797                                                'string'        => $p->fake_full_path,
1798                                                'relatives'     => array ($p->mask),
1799                                                'operaton'      => VFS_OPERATION_DELETED
1800                                        )
1801                                );
1802
1803                                $query = $GLOBALS['phpgw']->db->query ("DELETE FROM phpgw_vfs WHERE directory='".
1804                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
1805                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'" .
1806                                        $this->extra_sql (array ('query_type' => VFS_SQL_DELETE)), __LINE__, __FILE__);
1807
1808                                if ($this->file_actions)
1809                                {
1810                                        rmdir ($p->real_full_path);
1811                                }
1812
1813                                return True;
1814                        }
1815                }
1816
1817                /*
1818                 * See vfs_shared
1819                 */
1820                function mkdir ($data)
1821                {
1822                        if (!is_array ($data))
1823                        {
1824                                $data = array ();
1825                        }
1826
1827                        $default_values = array
1828                                (
1829                                        'relatives'     => array (RELATIVE_CURRENT)
1830                                );
1831
1832                        $data = array_merge ($this->default_values ($data, $default_values), $data);
1833
1834                        $account_id = $GLOBALS['phpgw_info']['user']['account_id'];
1835                        $currentapp = $GLOBALS['phpgw_info']['flags']['currentapp'];
1836
1837                        $p = $this->path_parts (array(
1838                                        'string'        => $data['string'],
1839                                        'relatives'     => array ($data['relatives'][0])
1840                                )
1841                        );
1842
1843                        if (!$this->acl_check (array(
1844                                        'string'        => $p->fake_full_path,
1845                                        'relatives'     => array ($p->mask),
1846                                        'operation'     => PHPGW_ACL_ADD)
1847                                )
1848                        )
1849                        {
1850                                return False;
1851                        }
1852
1853                        /* We don't allow /'s in dir names, of course */
1854                        if (ereg ("/", $p->fake_name))
1855                        {
1856                                return False;
1857                        }
1858
1859                        umask (077);
1860
1861                        if ($this->file_actions)
1862                        {
1863                                if (!@is_dir($p->real_leading_dirs_clean))      // eg. /home or /group does not exist
1864                                {
1865                                        if (!@mkdir($p->real_leading_dirs_clean,0770))  // ==> create it
1866                                        {
1867                                                return False;
1868                                        }
1869                                }
1870                                if (@is_dir($p->real_full_path))        // directory already exists
1871                                {
1872                                        $this->update_real($data,True);         // update its contents
1873                                }
1874                                elseif (!@mkdir ($p->real_full_path, 0770))
1875                                {
1876                                        return False;
1877                                }
1878                        }
1879
1880                        if (!$this->file_exists (array(
1881                                        'string'        => $p->fake_full_path,
1882                                        'relatives'     => array ($p->mask)
1883                                ))
1884                        )
1885                        {
1886                                $query = $GLOBALS['phpgw']->db->query ("INSERT INTO phpgw_vfs (owner_id, name, directory) VALUES ($this->working_id, '".
1887                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."', '".
1888                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."')", __LINE__, __FILE__);
1889       
1890                                $this->set_attributes(array(
1891                                        'string'        => $p->fake_full_path,
1892                                        'relatives'     => array ($p->mask),
1893                                        'attributes'    => array (
1894                                                                'createdby_id' => $account_id,
1895                                                                'size' => 4096,
1896                                                                'mime_type' => 'Directory',
1897                                                                'created' => $this->now,
1898                                                                'deleteable' => 'Y',
1899                                                                'app' => $currentapp
1900                                                        )
1901                                        )
1902                                );
1903
1904                                $this->correct_attributes (array(
1905                                                'string'        => $p->fake_full_path,
1906                                                'relatives'     => array ($p->mask)
1907                                        )
1908                                );
1909
1910                                $this->add_journal (array(
1911                                                'string'        => $p->fake_full_path,
1912                                                'relatives'     => array ($p->mask),
1913                                                'operation'     => VFS_OPERATION_CREATED
1914                                        )
1915                                );
1916                        }
1917                        else
1918                        {
1919                                return False;
1920                        }
1921
1922                        return True;
1923                }
1924
1925                /*
1926                 * See vfs_shared
1927                 */
1928                function make_link ($data)
1929                {
1930                        if (!is_array ($data))
1931                        {
1932                                $data = array ();
1933                        }
1934
1935                        $default_values = array
1936                                (
1937                                        'relatives'     => array (RELATIVE_CURRENT, RELATIVE_CURRENT)
1938                                );
1939
1940                        $data = array_merge ($this->default_values ($data, $default_values), $data);
1941
1942                        $account_id = $GLOBALS['phpgw_info']['user']['account_id'];
1943                        $currentapp = $GLOBALS['phpgw_info']['flags']['currentapp'];
1944
1945                        $vp = $this->path_parts (array(
1946                                        'string'        => $data['vdir'],
1947                                        'relatives'     => array ($data['relatives'][0])
1948                                )
1949                        );
1950
1951                        $rp = $this->path_parts (array(
1952                                        'string'        => $data['rdir'],
1953                                        'relatives'     => array ($data['relatives'][1])
1954                                )
1955                        );
1956
1957                        if (!$this->acl_check (array(
1958                                        'string'        => $vp->fake_full_path,
1959                                        'relatives'     => array ($vp->mask),
1960                                        'operation'     => PHPGW_ACL_ADD
1961                                ))
1962                        )
1963                        {
1964                                return False;
1965                        }
1966
1967                        if ((!$this->file_exists (array(
1968                                        'string'        => $rp->real_full_path,
1969                                        'relatives'     => array ($rp->mask)
1970                                )))
1971                                && !mkdir ($rp->real_full_path, 0770))
1972                        {
1973                                return False;
1974                        }
1975
1976                        if (!$this->mkdir (array(
1977                                        'string'        => $vp->fake_full_path,
1978                                        'relatives'     => array ($vp->mask)
1979                                ))
1980                        )
1981                        {
1982                                return False;
1983                        }
1984
1985                        $size = $this->get_size (array(
1986                                        'string'        => $rp->real_full_path,
1987                                        'relatives'     => array ($rp->mask)
1988                                )
1989                        );
1990
1991                        $this->set_attributes(array(
1992                                        'string'        => $vp->fake_full_path,
1993                                        'relatives'     => array ($vp->mask),
1994                                        'attributes'    => array (
1995                                                                'link_directory' => $rp->real_leading_dirs,
1996                                                                'link_name' => $rp->real_name,
1997                                                                'size' => $size
1998                                                        )
1999                                )
2000                        );
2001
2002                        $this->correct_attributes (array(
2003                                        'string'        => $vp->fake_full_path,
2004                                        'relatives'     => array ($vp->mask)
2005                                )
2006                        );
2007
2008                        return True;
2009                }
2010                function summary ($data)
2011                {
2012
2013                        if (!$this->acl_check (array(
2014                                        'string'        => $data['path'].'/'.$data['string'],
2015                                        'relatives'     => array (RELATIVE_NONE),
2016                                        'operation'     => PHPGW_ACL_READ
2017                                ))
2018                        )
2019                        {
2020                                return False;
2021                        }
2022
2023                        $query = "SELECT summary FROM phpgw_vfs WHERE directory = '"
2024                                .$data['path']."' AND name = '".$data['string']."' and mime_type != 'journal' and mime_type != 'journal-deleted' LIMIT 1";
2025                        if ($GLOBALS['phpgw']->db->query($query) && $GLOBALS['phpgw']->db->next_record()){
2026                                $val = $GLOBALS['phpgw']->db->row();
2027                                return $val['summary'];
2028                        }
2029                }
2030
2031                function set_summary($data){
2032                        if (!is_array ($data))
2033                        {
2034                                $data = array ();
2035                        }
2036
2037                        $default_values = array
2038                                (
2039                                        'relatives'     => array (RELATIVE_CURRENT),
2040                                        'attributes'    => array ()
2041                                );
2042
2043                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2044
2045                        $p = $this->path_parts (array(
2046                                        'string'        => $data['string'],
2047                                        'relatives'     => array ($data['relatives'][0])
2048                                )
2049                        );
2050                        if (!$this->acl_check (array(
2051                                        'string'        => $p->fake_full_path,
2052                                        'relatives'     => array ($p->mask),
2053                                        'operation'     => PHPGW_ACL_EDIT
2054                                ))
2055                        )
2056                        {
2057                                return False;
2058                        }
2059                        if (!$this->file_exists (array(
2060                                        'string'        => $data['string'],
2061                                        'relatives'     => array ($data['relatives'][0])
2062                                ))
2063                        )
2064                        {
2065                                return False;
2066                        }
2067                        $ls_array = $this->ls (array(
2068                                        'string'        => $p->fake_full_path,
2069                                        'relatives'     => array ($p->mask),
2070                                        'checksubdirs'  => False,
2071                                        'nofiles'       => True
2072                                )
2073                        );
2074                        $record = $ls_array[0];
2075                        $data['summary'] = pg_escape_bytea($data['summary']);
2076                        $sql = 'UPDATE phpgw_vfs SET summary = \''.$data['summary'].'\'';
2077                        $sql .= ' WHERE file_id='.(int) $ls_array[0]['file_id'];
2078                        $sql .= $this->extra_sql (array ('query_type' => VFS_SQL_UPDATE));
2079                        $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
2080                }
2081
2082                /*
2083                 * See vfs_shared
2084                 */
2085                function set_attributes ($data)
2086                {
2087                        if (!is_array ($data))
2088                        {
2089                                $data = array ();
2090                        }
2091
2092                        $default_values = array
2093                                (
2094                                        'relatives'     => array (RELATIVE_CURRENT),
2095                                        'attributes'    => array ()
2096                                );
2097
2098                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2099
2100                        $p = $this->path_parts (array(
2101                                        'string'        => $data['string'],
2102                                        'relatives'     => array ($data['relatives'][0])
2103                                )
2104                        );
2105
2106                        /*
2107                           This is kind of trivial, given that set_attributes () can change owner_id,
2108                           size, etc.
2109                        */
2110                        if (!$this->acl_check (array(
2111                                        'string'        => $p->fake_full_path,
2112                                        'relatives'     => array ($p->mask),
2113                                        'operation'     => PHPGW_ACL_EDIT
2114                                ))
2115                        )
2116                        {
2117                                return False;
2118                        }
2119
2120                        if (!$this->file_exists (array(
2121                                        'string'        => $data['string'],
2122                                        'relatives'     => array ($data['relatives'][0])
2123                                ))
2124                        )
2125                        {
2126                                return False;
2127                        }
2128
2129                        /*
2130                           All this voodoo just decides which attributes to update
2131                           depending on if the attribute was supplied in the 'attributes' array
2132                        */
2133
2134                        $ls_array = $this->ls (array(
2135                                        'string'        => $p->fake_full_path,
2136                                        'relatives'     => array ($p->mask),
2137                                        'checksubdirs'  => False,
2138                                        'nofiles'       => True
2139                                )
2140                        );
2141                        $record = $ls_array[0];
2142
2143                        $sql = 'UPDATE phpgw_vfs SET ';
2144
2145                        $change_attributes = 0;
2146
2147                        foreach ($this->attributes as $attribute)
2148                        {
2149                                if (isset ($data['attributes'][$attribute]))
2150                                {
2151                                        /*
2152                                           Indicate that the EDITED_COMMENT operation needs to be journaled,
2153                                           but only if the comment changed
2154                                        */
2155                                        if ($attribute == 'comment' && $data['attributes'][$attribute] != $record[$attribute])
2156                                        {
2157                                                $edited_comment = 1;
2158                                        }
2159
2160                                        if ($change_attributes > 0)
2161                                        {
2162                                                $sql .= ', ';
2163                                        }
2164
2165                                        // RalfBecker 2004/07/24:
2166                                        // this is only a hack to fix bug [ 991222 ] Error uploading file
2167                                        // the whole class need to be reworked with the new db-functions
2168                                        if (!isset($this->column_defs))
2169                                        {
2170                                                $table_defs = $GLOBALS['phpgw']->db->get_table_definitions('phpgwapi','phpgw_vfs');
2171                                                $this->column_defs = $table_defs['fd'];
2172                                        }
2173                                        $sql .= $attribute.'=' .$GLOBALS['phpgw']->db->quote($data['attributes'][$attribute],$this->column_defs[$attribute]['type']);
2174
2175                                        $change_attributes++;
2176                                }
2177                        }
2178
2179                        if (!$change_attributes)
2180                        {
2181                                return True;    // nothing to do
2182                        }
2183                        $sql .= ' WHERE file_id='.(int) $record['file_id'];
2184                        $sql .= $this->extra_sql (array ('query_type' => VFS_SQL_UPDATE));
2185                        $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
2186
2187                        if ($query)
2188                        {
2189                                if ($edited_comment)
2190                                {
2191                                        $this->add_journal (array(
2192                                                        'string'        => $p->fake_full_path,
2193                                                        'relatives'     => array ($p->mask),
2194                                                        'operation'     => VFS_OPERATION_EDITED_COMMENT
2195                                                )
2196                                        );
2197                                }
2198
2199                                return True;
2200                        }
2201                        else
2202                        {
2203                                return False;
2204                        }
2205                }
2206
2207                /*!
2208                @function correct_attributes
2209                @abstract Set the correct attributes for 'string' (e.g. owner)
2210                @param string File/directory to correct attributes of
2211                @param relatives Relativity array
2212                @result Boolean True/False
2213                */
2214                function correct_attributes ($data)
2215                {
2216                        if (!is_array ($data))
2217                        {
2218                                $data = array ();
2219                        }
2220
2221                        $default_values = array
2222                                (
2223                                        'relatives'     => array (RELATIVE_CURRENT)
2224                                );
2225
2226                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2227
2228                        $p = $this->path_parts (array(
2229                                        'string'        => $data['string'],
2230                                        'relatives'     => array ($data['relatives'][0])
2231                                )
2232                        );
2233
2234                        if ($p->fake_leading_dirs != $this->fakebase && $p->fake_leading_dirs != '/')
2235                        {
2236                                $ls_array = $this->ls (array(
2237                                                'string'        => $p->fake_leading_dirs,
2238                                                'relatives'     => array ($p->mask),
2239                                                'checksubdirs'  => False,
2240                                                'nofiles'       => True
2241                                        )
2242                                );
2243                                $set_attributes_array = Array(
2244                                        'owner_id' => $ls_array[0]['owner_id']
2245                                );
2246                        }
2247                        elseif (preg_match ("+^$this->fakebase\/(.*)$+U", $p->fake_full_path, $matches))
2248                        {
2249                                $set_attributes_array = Array(
2250                                        'owner_id' => $GLOBALS['phpgw']->accounts->name2id ($matches[1])
2251                                );
2252                        }
2253                        else
2254                        {
2255                                $set_attributes_array = Array(
2256                                        'owner_id' => 0
2257                                );
2258                        }
2259
2260                        $this->set_attributes (array(
2261                                        'string'        => $p->fake_full_name,
2262                                        'relatives'     => array ($p->mask),
2263                                        'attributes'    => $set_attributes_array
2264                                )
2265                        );
2266
2267                        return True;
2268                }
2269
2270                /*
2271                 * See vfs_shared
2272                 */
2273                function file_type ($data)
2274                {
2275                        if (!is_array ($data))
2276                        {
2277                                $data = array ();
2278                        }
2279
2280                        $default_values = array
2281                                (
2282                                        'relatives'     => array (RELATIVE_CURRENT)
2283                                );
2284
2285                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2286
2287                        $p = $this->path_parts (array(
2288                                        'string'        => $data['string'],
2289                                        'relatives'     => array ($data['relatives'][0])
2290                                )
2291                        );
2292
2293                        if (!$this->acl_check (array(
2294                                        'string'        => $p->fake_full_path,
2295                                        'relatives'     => array ($p->mask),
2296                                        'operation'     => PHPGW_ACL_READ,
2297                                        'must_exist'    => True
2298                                ))
2299                        )
2300                        {
2301                                return False;
2302                        }
2303
2304                        if ($p->outside)
2305                        {
2306                                if (is_dir ($p->real_full_path))
2307                                {
2308                                        return ('Directory');
2309                                }
2310
2311                                /*
2312                                   We don't return an empty string here, because it may still match with a database query
2313                                   because of linked directories
2314                                */
2315                        }
2316
2317                        /*
2318                           We don't use ls () because it calls file_type () to determine if it has been
2319                           passed a directory
2320                        */
2321                        $db2 = $GLOBALS['phpgw']->db;
2322                        $db2->query ("SELECT mime_type FROM phpgw_vfs WHERE directory='".
2323                                $db2->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2324                                $db2->db_addslashes($p->fake_name_clean)."'" . $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
2325                        $db2->next_record ();
2326                        $mime_type = $db2->Record['mime_type'];
2327                        if(!$mime_type)
2328                        {
2329                                $mime_type = $this->get_ext_mime_type (array ('string' => $data['string']));
2330                                {
2331                                        $db2->query ("UPDATE phpgw_vfs SET mime_type='$mime_type' WHERE directory='".
2332                                                $db2->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2333                                                $db2->db_addslashes($p->fake_name_clean)."'" .
2334                                                $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
2335                                }
2336                        }
2337
2338                        return $mime_type;
2339                }
2340
2341                /*
2342                 * See vfs_shared
2343                 */
2344                function file_exists ($data)
2345                {
2346                        if (!is_array ($data))
2347                        {
2348                                $data = array ();
2349                        }
2350
2351                        $default_values = array
2352                                (
2353                                        'relatives'     => array (RELATIVE_CURRENT)
2354                                );
2355
2356                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2357
2358                        $p = $this->path_parts (array(
2359                                        'string'        => $data['string'],
2360                                        'relatives'     => array ($data['relatives'][0])
2361                                )
2362                        );
2363
2364                        if ($p->outside)
2365                        {
2366                                $rr = file_exists ($p->real_full_path);
2367
2368                                return $rr;
2369                        }
2370
2371                        $db2 = $GLOBALS['phpgw']->db;
2372                        $db2->query ("SELECT name FROM phpgw_vfs WHERE directory='".
2373                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2374                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'" . $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
2375
2376                        if ($db2->next_record ())
2377                        {
2378                                return True;
2379                        }
2380                        else
2381                        {
2382                                return False;
2383                        }
2384                }
2385
2386                /*
2387                 * See vfs_shared
2388                 */
2389                function get_size ($data)
2390                {
2391                        if (!is_array ($data))
2392                        {
2393                                $data = array ();
2394                        }
2395
2396                        $default_values = array
2397                                (
2398                                        'relatives'     => array (RELATIVE_CURRENT),
2399                                        'checksubdirs'  => True
2400                                );
2401
2402                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2403
2404                        $p = $this->path_parts (array(
2405                                        'string'        => $data['string'],
2406                                        'relatives'     => array ($data['relatives'][0])
2407                                )
2408                        );
2409
2410                        if (!$this->acl_check (array(
2411                                        'string'        => $p->fake_full_path,
2412                                        'relatives'     => array ($p->mask),
2413                                        'operation'     => PHPGW_ACL_READ,
2414                                        'must_exist'    => True
2415                                ))
2416                        )
2417                        {
2418                                return False;
2419                        }
2420
2421                        /*
2422                           WIP - this should run through all of the subfiles/directories in the directory and tally up
2423                           their sizes.  Should modify ls () to be able to return a list for files outside the virtual root
2424                        */
2425                        if ($p->outside)
2426                        {
2427                                $size = filesize ($p->real_full_path);
2428
2429                                return $size;
2430                        }
2431
2432                        foreach($this->ls (array(
2433                                        'string'        => $p->fake_full_path,
2434                                        'relatives'     => array ($p->mask),
2435                                        'checksubdirs'  => $data['checksubdirs'],
2436                                        'nofiles'       => !$data['checksubdirs']
2437                                )) as $file_array)
2438                        {
2439                                /*
2440                                   Make sure the file is in the directory we want, and not
2441                                   some deeper nested directory with a similar name
2442                                */
2443/*
2444                                if (@!ereg ('^' . $file_array['directory'], $p->fake_full_path))
2445                                {
2446                                        continue;
2447                                }
2448*/
2449
2450                                $size += $file_array['size'];
2451                        }
2452
2453                        if ($data['checksubdirs'])
2454                        {
2455                                $query = $GLOBALS['phpgw']->db->query ("SELECT size FROM phpgw_vfs WHERE directory='".
2456                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2457                                        $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'" .
2458                                        $this->extra_sql (array ('query_text' => VFS_SQL_SELECT)));
2459                                $GLOBALS['phpgw']->db->next_record ();
2460                                $size += $GLOBALS['phpgw']->db->Record[0];
2461                        }
2462
2463                        return $size;
2464                }
2465                /*
2466                 * get the quota defined for the path in sql table
2467                 */
2468                function get_quota($data){
2469                        if (!is_array ($data))
2470                        {
2471                                $data = array ();
2472                        }
2473
2474                        $default_values = array
2475                                (
2476                                        'relatives'     => array (RELATIVE_CURRENT)
2477                                );
2478
2479                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2480
2481                        $p = $this->path_parts (array(
2482                                        'string'        => $data['string'],
2483                                        'relatives'     => RELATIVE_NONE
2484                                )
2485                        );
2486
2487                        if (!$this->acl_check (array(
2488                                'string'        => $p->fake_full_path,
2489                                'relatives'     => $p->mask,
2490                                'operation'     => PHPGW_ACL_READ
2491                        ))
2492                        )
2493                        {
2494                                return False;
2495                        }
2496                        $query = $GLOBALS['phpgw']->db->query ("SELECT quota_size FROM phpgw_vfs_quota WHERE directory = '".$data['string']."' LIMIT 1;", __LINE__,__FILE__);
2497
2498                        $GLOBALS['phpgw']->db->next_record ();
2499                        $record = $GLOBALS['phpgw']->db->Record;
2500                        return $record['quota_size'];
2501                }
2502                function set_quota($data){
2503                        if (!is_array ($data))
2504                        {
2505                                $data = array ();
2506                        }
2507
2508                        $default_values = array
2509                                (
2510                                        'relatives'     => array (RELATIVE_CURRENT)
2511                                );
2512
2513                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2514
2515                        $p = $this->path_parts (array(
2516                                        'string'        => $data['string'],
2517                                        'relatives'     => array ($data['relatives'][0])
2518                                )
2519                        );
2520
2521                        if (!$this->acl_check (array(
2522                                'string'        => $p->fake_full_path,
2523                                'relatives'     => array ($p->mask),
2524                                'operation'     => PHPGW_ACL_READ
2525                        ))
2526                        )
2527                        {
2528                                return False;
2529                        }
2530                        return $GLOBALS['phpgw']->db->query("INSERT INTO phpgw_vfs_quota VALUES ('".$data['string']."',".$data['new_quota'].");", __LINE__,__FILE__);
2531                }
2532
2533
2534                /*!
2535                @function checkperms
2536                @abstract Check if $this->working_id has write access to create files in $dir
2537                @discussion Simple call to acl_check
2538                @param string Directory to check access of
2539                @param relatives Relativity array
2540                @result Boolean True/False
2541                */
2542                function checkperms ($data)
2543                {
2544                        if (!is_array ($data))
2545                        {
2546                                $data = array ();
2547                        }
2548
2549                        $default_values = array
2550                                (
2551                                        'relatives'     => array (RELATIVE_CURRENT)
2552                                );
2553
2554                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2555
2556                        $p = $this->path_parts (array(
2557                                        'string'        => $data['string'],
2558                                        'relatives'     => array ($data['relatives'][0])
2559                                )
2560                        );
2561
2562                        if (!$this->acl_check (array(
2563                                        'string'        => $p->fake_full_path,
2564                                        'relatives'     => array ($p->mask),
2565                                        'operation'     => PHPGW_ACL_ADD
2566                                ))
2567                        )
2568                        {
2569                                return False;
2570                        }
2571                        else
2572                        {
2573                                return True;
2574                        }
2575                }
2576
2577                /*
2578                 * See vfs_shared
2579                 * If $data['readlink'] then a readlink is tryed on the real file
2580                 * If $data['file_id'] then the file_id is used instead of a path
2581                 */
2582                function ls ($data)
2583                {
2584                        if (!is_array ($data))
2585                        {
2586                                $data = array ();
2587                        }
2588
2589                        $default_values = array
2590                                (
2591                                        'relatives'     => array (RELATIVE_CURRENT),
2592                                        'checksubdirs'  => True,
2593                                        'mime_type'     => False,
2594                                        'nofiles'       => False,
2595                                        'summary'       => False,
2596                                        'orderby'       => 'directory'
2597                                );
2598
2599                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2600
2601                        $p = $this->path_parts (array(
2602                                        'string'        => $data['string'],
2603                                        'relatives'     => array ($data['relatives'][0])
2604                                )
2605                        );
2606                        $dir = $p->fake_full_path;
2607                        if($data['summary'])
2608                                $this->attributes['summary'] = 'summary';
2609
2610                        /* If they pass us a file or 'nofiles' is set, return the info for $dir only */
2611                        if (@$data['file_id']
2612                                || ((($type = $this->file_type (array(
2613                                        'string'        => $dir,
2614                                        'relatives'     => array ($p->mask)
2615                                )) != 'Directory'))
2616                                || ($data['nofiles'])) && !$p->outside
2617                        )
2618                        {
2619                                /* SELECT all, the, attributes */
2620                                $sql = 'SELECT ';
2621
2622                                foreach ($this->attributes as $num => $attribute)
2623                                {
2624                                        if ($num)
2625                                        {
2626                                                $sql .= ', ';
2627                                        }
2628
2629                                        $sql .= $attribute;
2630                                }
2631
2632                                $sql .= " FROM phpgw_vfs WHERE ";
2633                                if (@$data['file_id'])
2634                                {
2635                                        $sql .= 'file_id='.(int)$data['file_id'];
2636                                }
2637                                else
2638                                {
2639                                        $sql .= " directory='".$GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND".
2640                                                " name='".$GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'".
2641                                                $this->extra_sql (array ('query_type' => VFS_SQL_SELECT));
2642                                }
2643                                $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
2644
2645                                $GLOBALS['phpgw']->db->next_record ();
2646                                $record = $GLOBALS['phpgw']->db->Record;
2647
2648                                /* We return an array of one array to maintain the standard */
2649                                $rarray = array ();
2650                                foreach($this->attributes as $attribute)
2651                                {
2652                                        if ($attribute == 'mime_type' && !$record[$attribute])
2653                                        {
2654                                                $db2 = $GLOBALS['phpgw']->db;
2655                                                $record[$attribute] = $this->get_ext_mime_type (array(
2656                                                                'string' => $p->fake_name_clean
2657                                                        )
2658                                                );
2659
2660                                                if($record[$attribute])
2661                                                {
2662                                                        $db2->query ("UPDATE phpgw_vfs SET mime_type='".$record[$attribute]."' WHERE directory='".
2663                                                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2664                                                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'" . $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
2665                                                }
2666                                        }
2667
2668                                        $rarray[0][$attribute] = $record[$attribute];
2669                                }
2670                                if ($this->file_actions && @$data['readlink'])  // test if file is a symlink and get it's target
2671                                {
2672                                        $rarray[0]['symlink'] = @readlink($p->real_full_path);
2673                                }
2674                                if($data['summary'])
2675                                        unset($this->attributes['summary']);
2676
2677                                return $rarray;
2678                        }
2679
2680                        //WIP - this should recurse using the same options the virtual part of ls () does
2681                        /* If $dir is outside the virutal root, we have to check the file system manually */
2682                        if ($p->outside)
2683                        {
2684                                if ($this->file_type (array(
2685                                                'string'        => $p->fake_full_path,
2686                                                'relatives'     => array ($p->mask)
2687                                        )) == 'Directory'
2688                                        && !$data['nofiles']
2689                                )
2690                                {
2691                                        $dir_handle = opendir ($p->real_full_path);
2692                                        while ($filename = readdir ($dir_handle))
2693                                        {
2694                                                if ($filename == '.' || $filename == '..')
2695                                                {
2696                                                        continue;
2697                                                }
2698
2699                                                $rarray[] = $this->get_real_info (array(
2700                                                                'string'        => $p->real_full_path . SEP . $filename,
2701                                                                'relatives'     => array ($p->mask)
2702                                                        )
2703                                                );
2704                                        }
2705                                }
2706                                else
2707                                {
2708                                        $rarray[] = $this->get_real_info (array(
2709                                                        'string'        => $p->real_full_path,
2710                                                        'relatives'     => array ($p->mask)
2711                                                )
2712                                        );
2713                                }
2714
2715                                return $rarray;
2716                        }
2717
2718                        /* $dir's not a file, is inside the virtual root, and they want to check subdirs */
2719                        /* SELECT all, the, attributes FROM phpgw_vfs WHERE file=$dir */
2720                        $sql = 'SELECT ';
2721                        if (!$this->acl_check (array (
2722                                'string' => $p->fake_full_path,
2723                                'relatives' => array ($p->mask),
2724                                'operation' => PHPGW_ACL_PRIVATE)
2725                        ))
2726                        $query_type = " type != 1 AND";
2727                        else
2728                                $query_type = "";
2729
2730                        foreach($this->attributes as $num => $attribute)
2731                        {
2732                                if ($num)
2733                                {
2734                                        $sql .= ", ";
2735                                }
2736
2737                                $sql .= $attribute;
2738                        }
2739
2740                        $dir_clean = $this->clean_string (array ('string' => $dir));
2741                        $sql .= " FROM phpgw_vfs WHERE ".$query_type." directory LIKE '".$GLOBALS['phpgw']->db->db_addslashes($dir_clean)."%'";
2742                        $sql .= $this->extra_sql (array ('query_type' => VFS_SQL_SELECT));
2743
2744                        if ($data['mime_type'])
2745                        {
2746                                $sql .= " AND mime_type='".$data['mime_type']."'";
2747                        }
2748                        if (strlen($data['orderby']) > 0)
2749                                $sql .= ' ORDER BY '.$data['orderby'];
2750                        $query = $GLOBALS['phpgw']->db->query ($sql, __LINE__, __FILE__);
2751
2752                        $rarray = array ();
2753                        for ($i = 0; $GLOBALS['phpgw']->db->next_record (); $i++)
2754                        {
2755                                $record = $GLOBALS['phpgw']->db->Record;
2756
2757                                /* Further checking on the directory.  This makes sure /home/user/test won't match /home/user/test22 */
2758                                if (@!ereg ("^$dir(/|$)", $record['directory']))
2759                                {
2760                                        continue;
2761                                }
2762
2763                                /* If they want only this directory, then $dir should end without a trailing / */
2764                                if (!$data['checksubdirs'] && ereg ("^$dir/", $record['directory']))
2765                                {
2766                                        continue;
2767                                }
2768
2769                                foreach($this->attributes as $attribute)
2770                                {
2771                                        if ($attribute == 'mime_type' && !$record[$attribute])
2772                                        {
2773                                                $db2 = $GLOBALS['phpgw']->db;
2774                                                $record[$attribute] = $this->get_ext_mime_type (array(
2775                                                                'string'        => $p->fake_name_clean
2776                                                        )
2777                                                );
2778
2779                                                if($record[$attribute])
2780                                                {
2781                                                        $db2->query ("UPDATE phpgw_vfs SET mime_type='".$record[$attribute]."' WHERE directory='".
2782                                                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2783                                                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'" . $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
2784                                                }
2785                                        }
2786
2787                                        $rarray[$i][$attribute] = $record[$attribute];
2788                                }
2789                        }
2790
2791                        return $rarray;
2792                }
2793
2794                /*
2795                 * See vfs_shared
2796                 */
2797                function update_real ($data,$recursive = False)
2798                {
2799                        if (!is_array ($data))
2800                        {
2801                                $data = array ();
2802                        }
2803
2804                        $default_values = array
2805                                (
2806                                        'relatives'     => array (RELATIVE_CURRENT)
2807                                );
2808
2809                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2810
2811                        $p = $this->path_parts (array(
2812                                        'string'        => $data['string'],
2813                                        'relatives'     => array ($data['relatives'][0])
2814                                )
2815                        );
2816
2817                        if (file_exists ($p->real_full_path))
2818                        {
2819                                if (is_dir ($p->real_full_path))
2820                                {
2821                                        $dir_handle = opendir ($p->real_full_path);
2822                                        while ($filename = readdir ($dir_handle))
2823                                        {
2824                                                if ($filename == '.' || $filename == '..')
2825                                                {
2826                                                        continue;
2827                                                }
2828
2829                                                $rarray[] = $this->get_real_info (array(
2830                                                                'string'        => $p->fake_full_path . '/' . $filename,
2831                                                                'relatives'     => array (RELATIVE_NONE)
2832                                                        )
2833                                                );
2834                                        }
2835                                }
2836                                else
2837                                {
2838                                        $rarray[] = $this->get_real_info (array(
2839                                                        'string'        => $p->fake_full_path,
2840                                                        'relatives'     => array (RELATIVE_NONE)
2841                                                )
2842                                        );
2843                                }
2844
2845                                if (!is_array ($rarray))
2846                                {
2847                                        $rarray = array ();
2848                                }
2849
2850                                foreach($rarray as $num => $file_array)
2851                                {
2852                                        $p2 = $this->path_parts (array(
2853                                                        'string'        => $file_array['directory'] . '/' . $file_array['name'],
2854                                                        'relatives'     => array (RELATIVE_NONE)
2855                                                )
2856                                        );
2857
2858                                        /* Note the mime_type.  This can be "Directory", which is how we create directories */
2859                                        $set_attributes_array = Array(
2860                                                'size' => $file_array['size'],
2861                                                'mime_type' => $file_array['mime_type']
2862                                        );
2863
2864                                        if (!$this->file_exists (array(
2865                                                        'string'        => $p2->fake_full_path,
2866                                                        'relatives'     => array (RELATIVE_NONE)
2867                                                ))
2868                                        )
2869                                        {
2870                                                $this->touch (array(
2871                                                                'string'        => $p2->fake_full_path,
2872                                                                'relatives'     => array (RELATIVE_NONE)
2873                                                        )
2874                                                );
2875                                        }
2876                                        $this->set_attributes (array(
2877                                                        'string'        => $p2->fake_full_path,
2878                                                        'relatives'     => array (RELATIVE_NONE),
2879                                                        'attributes'    => $set_attributes_array
2880                                                )
2881                                        );
2882                                        if ($recursive && $file_array['mime_type'] == 'Directory')
2883                                        {
2884                                                $dir_data = $data;
2885                                                $dir_data['string'] = $file_array['directory'] . '/' . $file_array['name'];
2886                                                $this->update_real($dir_data,$recursive);
2887                                        }
2888                                }
2889                        }
2890                }
2891
2892                /* Helper functions */
2893
2894                /* This fetchs all available file system information for string (not using the database) */
2895                function get_real_info ($data)
2896                {
2897                        if (!is_array ($data))
2898                        {
2899                                $data = array ();
2900                        }
2901
2902                        $default_values = array
2903                                (
2904                                        'relatives'     => array (RELATIVE_CURRENT)
2905                                );
2906
2907                        $data = array_merge ($this->default_values ($data, $default_values), $data);
2908
2909                        $p = $this->path_parts (array(
2910                                        'string'        => $data['string'],
2911                                        'relatives'     => array ($data['relatives'][0])
2912                                )
2913                        );
2914
2915                        if (is_dir ($p->real_full_path))
2916                        {
2917                                $mime_type = 'Directory';
2918                        }
2919                        else
2920                        {
2921                                $mime_type = $this->get_ext_mime_type (array(
2922                                                'string'        => $p->fake_name
2923                                        )
2924                                );
2925
2926                                if($mime_type)
2927                                {
2928                                        $GLOBALS['phpgw']->db->query ("UPDATE phpgw_vfs SET mime_type='".$mime_type."' WHERE directory='".
2929                                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_leading_dirs_clean)."' AND name='".
2930                                                $GLOBALS['phpgw']->db->db_addslashes($p->fake_name_clean)."'" .
2931                                                $this->extra_sql (array ('query_type' => VFS_SQL_SELECT)), __LINE__, __FILE__);
2932                                }
2933                        }
2934
2935                        $size = filesize ($p->real_full_path);
2936                        $rarray = array(
2937                                'directory' => $p->fake_leading_dirs,
2938                                'name' => $p->fake_name,
2939                                'size' => $size,
2940                                'mime_type' => $mime_type
2941                        );
2942
2943                        return ($rarray);
2944                }
2945        }
2946?>
Note: See TracBrowser for help on using the repository browser.