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

Revision 1830, 71.3 KB checked in by amuller, 14 years ago (diff)

Ticket #597 - Melhoria do FM, miniatura thumbnail de imagens

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