Ubuntu Package modification - Added configuration of max_input_vars setting
[openemr.git] / library / acl.inc
blob8a5fbd90b843acae8aecda13ead8418d4d445a0e
1 <?php
2 /**
3  * library/acl.inc 
4  * 
5  * Functions wrapping php-GACL's functionality, to create a generic OpenEMR access control system.
6  *
7  * LICENSE: This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see 
17  * http://www.gnu.org/licenses/licenses.html#GPL .
18  *
19  * @package OpenEMR
20  * @license http://www.gnu.org/licenses/licenses.html#GPL GNU GPL V3+
21  * @author  Brady Miller <brady@sparmy.com>
22  * @author  Rod Roark <rod@sunsetsystems.com>
23  * @link    http://www.open-emr.org
24  */
26 // php-GACL access controls are included in OpenEMR. The below
27 // function will automatically create the path where gacl.class.php
28 // can be found. Note that this path can be manually set below
29 // for users who are using an external version of php-GACL.
30 // Also note that php-GACL access controls can be turned off
31 // below.
33   $phpgacl_location = dirname(__FILE__).'/../gacl';
35 // If using an external version of phpGACL, then uncomment the following
36 // line and manually place the path below.  IN THIS CASE YOU MUST ALSO
37 // COMMENT OUT ABOVE $phpgacl_location ASSIGNMENT ABOVE, OR BACKUPS WILL
38 // NOT RESTORE PROPERLY!
40 //$phpgacl_location = "/var/www/gacl";
42 // If you want to turn off php-GACL, then uncomment the following line.
43 // IN THIS CASE YOU MUST ALSO COMMENT OUT ABOVE $phpgacl_location ASSIGNMENT(S)
44 // ABOVE, OR BACKUPS WILL NOT RESTORE PROPERLY!
46 //unset($phpgacl_location);
49   // The following Access Control Objects (ACO) are currently supported.
50   // These are the "things to be protected":
51   //
52   // Section "admin" (Administration):
53   //   super       Superuser - can delete patients, encounters, issues
54   //   calendar    Calendar Settings
55   //   database    Database Reporting
56   //   forms       Forms Administration
57   //   practice    Practice Settings
58   //   superbill   Superbill Codes Administration
59   //   users       Users/Groups/Logs Administration
60   //   batchcom    Batch Communication Tool
61   //   language    Language Interface Tool
62   //   drugs       Pharmacy Dispensary
63   //   acl         ACL Administration
64   //
65   // Section "acct" (Accounting):
66   //   bill        Billing (write optional)
67   //   disc        Allowed to discount prices (in Fee Sheet or Checkout form)
68   //   eob         EOB Data Entry
69   //   rep         Financial Reporting - my encounters
70   //   rep_a       Financial Reporting - anything
71   //
72   // Section "patients" (Patient Information):
73   //   appt        Appointments (write,wsome optional)
74   //   demo        Demographics (write,addonly optional)
75   //   med         Medical Records and History (write,addonly optional)
76   //   trans       Transactions, e.g. referrals (write optional)
77   //   docs        Documents (write,addonly optional)
78   //   notes       Patient Notes (write,addonly optional)
79   //   sign        Sign Lab Results (write,addonly optional)
80   //
81   // Section "encounters" (Encounter Information):
82   //   auth        Authorize - my encounters
83   //   auth_a      Authorize - any encounters
84   //   coding      Coding - my encounters (write,wsome optional)
85   //   coding_a    Coding - any encounters (write,wsome optional)
86   //   notes       Notes - my encounters (write,addonly optional)
87   //   notes_a     Notes - any encounters (write,addonly optional)
88   //   date_a      Fix encounter dates - any encounters
89   //   relaxed     Less-private information (write,addonly optional)
90   //               (e.g. the Sports Fitness encounter form)
91   //
92   // Section "squads" applies to sports team use only:
93   //   acos in this section define the user-specified list of squads
94   //
95   // Section "sensitivities" (Sensitivities):
96   //   normal     Normal
97   //   high       High
98   //
99   // Section "lists" (Lists):
100   //   default    Default List (write,addonly optional)
101   //   state      State List (write,addonly optional)
102   //   country    Country List (write,addonly optional)
103   //   language   Language List (write,addonly optional)
104   //   ethrace    Ethnicity-Race List (write,addonly optional)
105   //
106   // Section "placeholder" (Placeholder):
107   //   filler     Placeholder (Maintains empty ACLs)
108   //
109   // Section "nationnotes" (Nation Notes):
110   //   nn_configure     Nation Notes
111   //
112   // Section "patientportal" (Patient Portal):
113   //   portal     Patient Portal
114   
115   if (isset ($phpgacl_location)) {
116     $GLOBALS['phpgacl_location_global'] = $phpgacl_location;
117     require_once("$phpgacl_location/gacl.class.php");
118     $gacl_object = new gacl();
119     //DO NOT CHANGE BELOW VARIABLE
120     $section_aro_value = 'users';
121     $GLOBALS['section_aro_value_global'] = $section_aro_value;
122   }
125  * Check if a user has a given type or types of access to an access control object.
127  * Globals that can use are:
128  *  $GLOBALS['phpgacl_location_global']
129  *  $GLOBALS['section_aro_value_global']
130  * 
131  * This function will check for access to the given ACO.
132  * view    - The user may view but not add or modify entries
133  * write   - The user may add or modify the ACO
134  * wsome   - The user has limited add/modify access to the ACO
135  * addonly - The user may view and add but not modify entries
137  * @param string       $section      Category of ACO
138  * @param string       $value        Subcategory of ACO
139  * @param string       $user         Optional user being checked for access.
140  * @param string|array $return_value Type or types of access being requested.
141  * @return bool|array  FALSE if access is denied, TRUE if allowed. An
142  *                     array() of bools is returned if $return_value is an
143  *                     array, representing results for each type of access
144  *                     requested.
145  */
146   function acl_check($section, $value, $user = '', $return_value = '') {
147     if (! $user) $user = $_SESSION['authUser'];
149     if ($GLOBALS['phpgacl_location_global']) {
150       // This will return all pertinent ACL's (including return_values and whether allow/deny)
151       // Walk through them to assess for access
152       $gacl_object = new gacl();
153       $acl_results = $gacl_object->acl_query($section, $value, $GLOBALS['section_aro_value_global'], $user,NULL,NULL,NULL,NULL,NULL,TRUE);
154       if (empty($acl_results)) {
155         return FALSE; //deny access
156       }
157       $access=FALSE; //flag
158       $deny=FALSE; //flag
159       foreach ($acl_results as $acl_result) {
160         if (empty($acl_result['acl_id'])) return FALSE; //deny access, since this happens if no pertinent ACL's are returned
161         if (is_array($return_value)) {
162           foreach ($return_value as $single_return_value) {
163             if (empty($single_return_value)) {
164               // deal with case if not looking for specific return value
165               if ($acl_result['allow']) {
166                 $access=TRUE;
167               }
168               else {
169                 $deny=TRUE;
170               }
171             }
172             else { //!empty($single_return_value)
173               // deal with case if looking for specific return value
174               if ($acl_result['return_value'] == $single_return_value) {
175                 if ($acl_result['allow']) {
176                   $access=TRUE;
177                 }
178                 else{
179                   $deny=TRUE;
180                 }
181               }
182             }
183           }
184         }
185         else { // $return_value is not an array (either empty or with one value)
186           if (empty($return_value)) {
187             // deal with case if not looking for specific return value
188             if ($acl_result['allow']) {
189               $access=TRUE;
190             }
191             else {
192               $deny=TRUE;
193             }
194           }
195           else { //!empty($return_value)
196             // deal with case if looking for specific return value
197             if ($acl_result['return_value'] == $return_value) {
198               if ($acl_result['allow']) {
199                 $access=TRUE;
200               }
201               else{
202                 $deny=TRUE;
203               }
204             }
205           }
206         }
207       }
209       // Now decide whether user has access
210       // (Note a denial takes precedence)
211       if ($deny) return FALSE;
212       if ($access) return TRUE;
213       return FALSE;
214     }
217     // If no phpgacl, then apply the old static rules whereby "authorized"
218     // users (providers) can do anything, and other users can do most things.
219     // If you want custom access control but don't want to mess with phpGACL,
220     // then you could customize the code below instead.
222     if ($user == 'admin') return 'write';
223     if ($section == 'admin' && $value == 'super') return 0;
224     if ($_SESSION['userauthorized']) return 'write';
226     if ($section == 'patients') {
227       if ($value == 'med') return 1;
228       return 'write';
229     }
230     else if ($section == 'encounters') {
231       if (strpos($value, 'coding' ) === 0) return 'write';
232       if (strpos($value, 'notes'  ) === 0) return 'write';
233       if ($value == 'relaxed') return 'write';
234     }
235     else if ($section != 'admin') {
236       return 'write';
237     }
239     return 0;
240   }
242   // Get the ACO name/value pairs for a designated section.  Each value
243   // is an array (section_value, value, order_value, name, hidden).
244   //
245   function acl_get_section_acos($section) {
246     global $phpgacl_location;
247     if ($phpgacl_location) {
248       include_once("$phpgacl_location/gacl_api.class.php");
249       $gacl = new gacl_api();
250       $arr1 = $gacl->get_objects($section, 1, 'ACO');
251       $arr = array();
252       if (!empty($arr1[$section])) {
253         foreach ($arr1[$section] as $value) {
254           $odata = $gacl->get_object_data($gacl->get_object_id($section, $value, 'ACO'), 'ACO');
255           $arr[$value] = $odata[0];
256         }
257       }
258       return $arr;
259     }
260     return 0;
261   }
263   // Sort squads by their order value.  Used only by acl_get_squads().
264   function _acl_squad_compare($a, $b) {
265     if ($a[2] == $b[2]) {
266       // If order value is the same, sort by squad name.
267       if ($a[3] == $b[3]) return 0;
268       return ($a[3] < $b[3]) ? -1 : 1;
269     }
270     return ($a[2] < $b[2]) ? -1 : 1;
271   }
273   // Return an array keyed on squad ACO names.
274   // This is only applicable for sports team use.
275   //
276   function acl_get_squads() {
277     $squads = acl_get_section_acos('squads');
278     uasort($squads, "_acl_squad_compare");
279     return $squads;
280   }
282   // Return an array keyed on encounter sensitivity level ACO names.
283   // Sensitivities are useful when some encounter notes are not
284   // medically sensitive (e.g. a physical fitness test), and/or if
285   // some will be "for doctor's eyes only" (e.g. STD treatment).
286   //
287   // When a non-blank sensitivity value exists in the new encounter
288   // form, it names an additional ACO required for access to all forms
289   // in the encounter.  If you want some encounters to be non-sensitive,
290   // then you also need some default nonblank sensitivity for normal
291   // encounters, as well as greater encounter notes permissions for
292   // those allowed to view non-sensitive encounters.
293   //
294   function acl_get_sensitivities() {
295     return acl_get_section_acos('sensitivities');
296   }
298   //
299   // Returns true if aco exist
300   // Returns false if aco doesn't exist
301   //    $section_name = name of section (string)
302   //    $aco_name = name of aco (string)
303   //
304   function aco_exist($section_name, $aco_name) {
305    global $phpgacl_location;
306    if (isset ($phpgacl_location)) {
307     include_once("$phpgacl_location/gacl_api.class.php");
308     $gacl = new gacl_api();
309     $aco_id = $gacl->get_object_id($section_name,  $aco_name, 'ACO');
310     if ($aco_id) {
311      return true;
312     }
313    }
314    return false;
315   }
317   //
318   // Returns a sorted array of all available Group Titles.
319   //
320   function acl_get_group_title_list() {
321     global $phpgacl_location;
322     if (isset ($phpgacl_location)) {
323       include_once("$phpgacl_location/gacl_api.class.php");
324       $gacl = new gacl_api();
325       $parent_id = $gacl->get_root_group_id();
326       $arr_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
327       $arr_group_titles = array();
328       foreach ($arr_group_ids as $value) {
329         $arr_group_data = $gacl->get_group_data($value, 'ARO');
330         $arr_group_titles[$value] = $arr_group_data[3];
331       }
332       sort($arr_group_titles);
333       return $arr_group_titles;
334     }
335     return 0;
336   }
338   //
339   // Returns a sorted array of group Titles that a user belongs to.
340   // Returns 0 if does not belong to any group yet.
341   //   $user_name = Username, which is login name.
342   //
343   function acl_get_group_titles($user_name) {
344     global $phpgacl_location, $section_aro_value;
345     if (isset ($phpgacl_location)) {
346       include_once("$phpgacl_location/gacl_api.class.php");
347       $gacl = new gacl_api();
348       $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
349       if ($user_aro_id) {
350         $arr_group_id = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
351         if ($arr_group_id) {
352           foreach ($arr_group_id as $key => $value) {
353             $arr_group_data = $gacl->get_group_data($value, 'ARO');
354             $arr_group_titles[$key] =  $arr_group_data[3];
355           }
356         sort($arr_group_titles);
357         return $arr_group_titles;
358         }
359       }
360     }
361     return 0;
362   }
364   //
365   // This will place the user aro object into selected group(s)
366   // It uses the set_user_aro() function
367   //   $username = username (string)
368   //   $group = title of group(s) (string or array)
369   //
370   function add_user_aros($username, $group) {
371    $current_user_groups = acl_get_group_titles($username);
372    if (!$current_user_groups) {
373     $current_user_groups = array();
374    }
375    if (is_array($group)){
376     foreach ($group as $value) {
377        if (!in_array($value, $current_user_groups)) { 
378         array_push($current_user_groups, $value);
379        }
380     }
381    }
382    else {
383     if (!in_array($group, $current_user_groups)) {
384      array_push($current_user_groups, $group);
385     }
386    }
387    $user_data = mysql_fetch_array(sqlStatement("select * from users where username='" .
388     $username . "'"));
389    set_user_aro($current_user_groups, $username, $user_data["fname"],
390     $user_data["mname"], $user_data["lname"]);
391    return;
392   }
394   //
395   // This will remove the user aro object from the selected group(s)
396   // It uses the set_user_aro() function
397   //   $username = username (string)
398   //   $group = title of group(s) (string or array)
399   //
400   function remove_user_aros($username, $group) {
401    $current_user_groups = acl_get_group_titles($username);
402    $new_user_groups = array();
403    if (is_array($group)){
404     foreach ($current_user_groups as $value) {
405      if (!in_array($value, $group)) {
406       array_push($new_user_groups, $value);
407      }
408     }
409    }
410    else {
411     foreach ($current_user_groups as $value) {
412      if ($value != $group) {
413       array_push($new_user_groups, $value);
414      }
415     }
416    }
417    $user_data = mysql_fetch_array(sqlStatement("select * from users where username='" .
418     $username . "'"));
419    set_user_aro($new_user_groups, $username, $user_data["fname"],
420     $user_data["mname"], $user_data["lname"]);
421    return;
422   }
424   //
425   // This will either create or edit a user aro object, and then place it
426   // in the requested groups. It will not allow removal of the 'admin'
427   // user or gacl_protected users from the 'admin' group.
428   //   $arr_group_titles = titles of the groups that user will be added to.
429   //   $user_name = username, which is login name.
430   //   $first_name = first name
431   //   $middle_name = middle name
432   //   $last_name = last name
433   //
434   function set_user_aro($arr_group_titles, $user_name, $first_name, $middle_name, $last_name) {
435     global $phpgacl_location, $section_aro_value;
437     if (isset ($phpgacl_location)) {
438       include_once("$phpgacl_location/gacl_api.class.php");
439       $gacl = new gacl_api();
441       //see if this user is gacl protected (ie. do not allow
442       //removal from the Administrators group)
443       require_once(dirname(__FILE__).'/user.inc');
444       require_once(dirname(__FILE__).'/calendar.inc');
445       $userNametoID = getIDfromUser($user_name);
446       if (checkUserSetting("gacl_protect","1",$userNametoID) || $user_name == "admin") {
447         $gacl_protect = true;
448       }
449       else {
450         $gacl_protect = false;
451       }
453       //get array of all available group ID numbers
454       $parent_id = $gacl->get_root_group_id();
455       $arr_all_group_ids = $gacl->get_group_children($parent_id, 'ARO', 'RECURSE');
457       //Cycle through ID array to find and process each selected group
458       //Create a counter since processing of first hit is unique
459       $counter = 0;
460       foreach ($arr_all_group_ids as $value) {
461         $arr_group_data = $gacl->get_group_data($value, 'ARO');
462         if ((empty($arr_group_titles)) ||
463          (in_array($arr_group_data[3], $arr_group_titles))) {
464           //We have a hit, so need to add group and increment counter
465           // because processing of first hit is unique
466           //This will also deal with an empty $arr_group_titles array
467           // removing user from all groups unless 'admin'
468           $counter = $counter + 1;
469           //create user full name field
470           if ($middle_name) {
471             $full_name = $first_name . " " . $middle_name . " " .  $last_name;
472           }
473           else {
474             if ($last_name) {
475               $full_name = $first_name . " " . $last_name;
476             }
477             else {
478               $full_name = $first_name;
479             }
480           }
482           //If this is not the first group to be added, then will skip below
483           // and will be added. If this is the first group, then need to
484           // go thru several steps before adding the group.
485           if ($counter == 1) {
486             //get ID of user ARO object, if it exist
487             $user_aro_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
488             if ($user_aro_id) {
489               //user ARO object already exist, so will edit it
490               $gacl->edit_object($user_aro_id, $section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
492               //remove all current user ARO object group associations
493               $arr_remove_group_ids = $gacl->get_object_groups($user_aro_id, 'ARO', 'NO_RECURSE');
494               foreach ($arr_remove_group_ids as $value2) {
495                 $gacl->del_group_object($value2, $section_aro_value, $user_name, 'ARO');
496               }
497             }
498             else {
499               //user ARO object does not exist, so will create it
500               $gacl->add_object($section_aro_value, $full_name, $user_name, 10, 0, 'ARO');
501             }
502           }
504           //place the user ARO object in the selected group (if group(s) is selected)
505           if (!empty($arr_group_titles)) {
506             $gacl->add_group_object($value, $section_aro_value, $user_name, 'ARO');
507           }
509           //
510           //Below will not allow 'admin' or gacl_protected user to be removed from 'admin' group
511           //
512           if ($gacl_protect) {
513             $boolean_admin=0;
514             $admin_id = $gacl->get_object_id($section_aro_value, $user_name, 'ARO');
515             $arr_admin = $gacl->get_object_groups($admin_id, 'ARO', 'NO_RECURSE');
516             foreach ($arr_admin as $value3) {
517               $arr_admin_data = $gacl->get_group_data($value3, 'ARO');
518               if (strcmp($arr_admin_data[2], 'admin') == 0) {
519                 $boolean_admin=1;
520               }
521             }
522             if (!$boolean_admin) {
523               foreach ($arr_all_group_ids as $value4) {
524                 $arr_temp = $gacl->get_group_data($value4, 'ARO');
525                 if ($arr_temp[2] == 'admin') {
526                   $gacl->add_group_object($value4, $section_aro_value, $user_name, 'ARO');
527                 }
528               }
529             }
530           }
531         }
532         //if array of groups was empty, then we are done, and can break from loop
533         if (empty($arr_group_titles)) break;
534       }
535       return true;
536     }
537    return false;
538   }
540   //
541   // Returns true if acl exist
542   // Returns false if acl doesn't exist
543   //  EITHER $title or $name is required(send FALSE in variable
544   //  not being used). If both are sent, then only $title will be
545   //  used.
546   //  $return_value is required
547   //    $title = title of acl (string)
548   //    $name = name of acl (string)
549   //    $return_value = return value of acl (string)
550   //
551   function acl_exist($title, $name, $return_value) {
552    global $phpgacl_location;
553    if (isset ($phpgacl_location)) {
554     include_once("$phpgacl_location/gacl_api.class.php");
555     $gacl = new gacl_api();
556     if (!$name) {
557      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
558     }
559     else if (!$title) {
560      $group_id = $gacl->get_group_id($name, NULL, 'ARO');
561      if ($group_id) {
562       $group_data = $gacl->get_group_data($group_id, 'ARO');
563       $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $group_data[3], FALSE, FALSE, FALSE, $return_value);
564      }
565      else {
566      return false;
567      }
568     }
569     else {
570      $acl = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $title, FALSE, FALSE, FALSE, $return_value);
571     }
572     if (!empty($acl)) {
573      return true;
574     }
575     else {
576      return false;
577     }
578    }
579   }
581   //
582   // This will add a new acl and group(if group doesn't yet exist)
583   // with one aco in it.
584   //   $acl_title = title of acl (string)
585   //   $acl_name = name of acl (string)
586   //   $return_value = return value of acl (string)
587   //   $note = description of acl (array)
588   //
589   function acl_add($acl_title, $acl_name, $return_value, $note) {
590    global $phpgacl_location;
591    if (isset ($phpgacl_location)) {
592     include_once("$phpgacl_location/gacl_api.class.php");
593     $gacl = new gacl_api();
594     $group_id = $gacl->get_group_id($acl_name, $acl_title, 'ARO');
595     if ($group_id) {
596      //group already exist, so just create acl
597      $gacl->add_acl(array("placeholder"=>array("filler")),
598       NULL, array($group_id), NULL, NULL, 1, 1, $return_value, $note);
599     }
600     else {
601      //create group, then create acl
602      $parent_id = $gacl->get_root_group_id();
603      $aro_id = $gacl->add_group($acl_name, $acl_title, $parent_id, 'ARO');
604      $gacl->add_acl(array("placeholder"=>array("filler")),
605       NULL, array($aro_id), NULL, NULL, 1, 1, $return_value, $note);
606     }
607     return;
608    }
609    return 0;
610   }
612   //
613   // This will remove acl. It will also remove group(if the group
614   // is no longer associated with any acl's).
615   //   $acl_title = title of acl (string)
616   //   $acl_name = name of acl (string)
617   //   $return_value = return value of acl (string)
618   //   $note = description of acl (array)
619   //
620   function acl_remove($acl_title, $return_value) {
621    global $phpgacl_location;
622    if (isset ($phpgacl_location)) {
623     include_once("$phpgacl_location/gacl_api.class.php");
624     $gacl = new gacl_api();
625     //First, delete the acl
626     $acl_id=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
627     $gacl->del_acl($acl_id[0]);
628     //Then, remove the group(if no more acl's are remaining)
629     $acl_search=$gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, FALSE);
630     if (empty($acl_search)){
631      $group_id=$gacl-> get_group_id(NULL, $acl_title, 'ARO');
632      $gacl->del_group($group_id, TRUE, 'ARO');
633     }
634     return;
635    }
636    return 0;
637   }
639   //
640   // This will place the aco(s) into the selected acl
641   //   $acl_title = title of acl (string)
642   //   $return_value = return value of acl (string)
643   //   $aco_id = id of aco (array)
644   //
645   function acl_add_acos($acl_title, $return_value, $aco_id) {
646    global $phpgacl_location;
647    if (isset ($phpgacl_location)) {
648     include_once("$phpgacl_location/gacl_api.class.php");
649     $gacl = new gacl_api();
650     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
651     foreach ($aco_id as $value) { 
652      $aco_data = $gacl->get_object_data($value, 'ACO');
653      $aco_section = $aco_data[0][0];
654      $aco_name = $aco_data[0][1];   
655      $gacl->append_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
656     }
657     return;
658    }
659    return 0;
660   }
662   //
663   // This will remove the aco(s) from the selected acl
664   //  Note if all aco's are removed, then will place the filler-placeholder
665   //  into the acl to avoid complete removal of the acl.
666   //   $acl_title = title of acl (string)
667   //   $return_value = return value of acl (string)
668   //   $aco_id = id of aco (array)
669   //
670   function acl_remove_acos($acl_title, $return_value, $aco_id) {
671    global $phpgacl_location;
672    if (isset ($phpgacl_location)) {
673     include_once("$phpgacl_location/gacl_api.class.php");
674     $gacl = new gacl_api();
675     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
677     // Check to see if removing all acos. If removing all acos then will
678     //  ensure the filler-placeholder aco in acl to avoid complete
679     //  removal of the acl.
680     if (count($aco_id) == acl_count_acos($acl_title, $return_value)) {
681      //1-get the filler-placeholder aco id
682      $filler_aco_id = $gacl->get_object_id('placeholder','filler','ACO');     
683      //2-add filler-placeholder aco
684      acl_add_acos($acl_title, $return_value, array($filler_aco_id));
685      //3-ensure filler-placeholder aco is not to be deleted
686      $safeListaco = remove_element($_POST["selection"],$filler_aco_id);
687      //4-prepare to safely delete the acos
688      $aco_id = $safeListaco;
689     }
691     foreach ($aco_id as $value) {
692      $aco_data = $gacl->get_object_data($value, 'ACO');
693      $aco_section = $aco_data[0][0];
694      $aco_name = $aco_data[0][1];
695      $gacl->shift_acl($acl_id[0], NULL, NULL, NULL, NULL, array($aco_section=>array($aco_name)));
696      }
697     return;
698    }
699    return 0;
700   }
702   //
703   // This will return the number of aco objects
704   //  in a specified acl.
705   //   $acl_title = title of acl (string)
706   //   $return_value = return value of acl (string)
707   //
708   function acl_count_acos($acl_title, $return_value) {
709    global $phpgacl_location;
710    if (isset ($phpgacl_location)) {
711     include_once("$phpgacl_location/gacl_api.class.php");
712     $gacl = new gacl_api();
713     $acl_id = $gacl->search_acl(FALSE, FALSE, FALSE, FALSE, $acl_title, FALSE, FALSE, FALSE, $return_value);
714     $acl_data = $gacl->get_acl($acl_id[0]);
715     $aco_count = 0;
716     foreach ($acl_data['aco'] as $key => $value) {
717      $aco_count = $aco_count + count($acl_data['aco'][$key]);
718     }
719     return $aco_count;
720    }
721    return 0;
722   }
724   //
725   // Function to remove an element from an array
726   //
727   function remove_element($arr, $val){
728    $arr2 = array();
729    foreach ($arr as $value){
730     if ($value != $val) {
731      array_push($arr2,$value);
732     }
733    }
734    return $arr2;
735   }