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

Revision 1627, 69.1 KB checked in by amuller, 14 years ago (diff)

Ticket #597 - Implementações novas, com arquivos restritos, quota, ckeditor

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