Example #1
0
function get_open_gates($gate, $pregates = array())
{
    $inherits = $GLOBALS['inherit_code'][$gate];
    if (!empty($inherits)) {
        foreach ($inherits as $tmpgate) {
            if (!in_array($tmpgate, $pregates)) {
                array_push($pregates, $tmpgate);
            }
            $pregates = get_open_gates($tmpgate, $pregates);
        }
    }
    return $pregates;
}
Example #2
0
function top_down_propagation_list($toFind, $root, $db, $Hlist = array(), $all_datafile = '', $all_sharedfile = '', $j = 0)
{
    global $timer;
    $n = 5;
    #top down propagation list finds the children, and the children's children , of the parents indicated in root. Propagation stops when the core element that is being seeked (toFInd) is reached.
    if (is_file($Hlist)) {
        $Hlist = unserialize(file_get_contents($Hlist));
    }
    if (is_file($all_data_file)) {
        $all_data = unserialize(file_get_contents($all_data_file));
        unlink($all_data_file);
    }
    if (is_file($all_sharedfile)) {
        $all_shared = unserialize(file_get_contents($all_sharedfile));
        unlink($all_sharedfile);
    }
    if (!is_array($root)) {
        $root = array($root);
    }
    $e = letter($toFind);
    $e_upstream = get_open_gates($e);
    #how many of the root are of the same kind? (that is, if
    $letters = array();
    foreach ($root as $p) {
        $l = letter($p);
        if (empty($letters[$l])) {
            $letters[$l] = 0;
            $parent_uid[$l] = array();
        }
        $letters[$l]++;
        array_push($parent_uid[$l], $p);
    }
    #for those that have + 10 elements and belong to the $e_upstream (that is, are open gates in the flood), search for every downstream element regardelss of parent id
    foreach ($letters as $pl => $p_times) {
        #these must be declared in order to find the correct parent id
        $p_element = $GLOBALS['s3codes'][$pl];
        $p_element_idname = $GLOBALS['COREids'][$p_element];
        $next_tables = $GLOBALS['next_element'][$pl];
        if (is_array($next_tables)) {
            foreach ($next_tables as $tC) {
                #qhery this only if this table has not been queried yet; since one row may contain several parents ((for example, a rule inherits from a project but also form the subject collection
                if (in_array($tC, $e_upstream) || $tC == $e) {
                    if (!is_array($all_data[$tC])) {
                        $element = $GLOBALS['s3codes'][$tC];
                        $tn = $GLOBALS['s3tables'][$GLOBALS['s3codes'][$tC]];
                        $tn_id = $GLOBALS['s3ids'][$element];
                        #beause collection and item are in the same table, this correction is needed; replace collection_id with "resource_class_id" in the query
                        $parent_id = $GLOBALS['s3map'][$GLOBALS['plurals'][$element]][$p_element_idname] != '' ? $GLOBALS['s3map'][$GLOBALS['plurals'][$element]][$p_element_idname] : $p_element_idname;
                        #retrieve all elements of this time from the table
                        $sql = "select * from s3db_" . $tn . "";
                        $connector = "where";
                        if ($tC == 'I') {
                            $sql .= " " . $connector . " iid='1'";
                            $connector = "and";
                        }
                        if ($tC == 'C') {
                            $sql .= " " . $connector . " iid='0'";
                            $connector = "and";
                        }
                        if ($tC == 'R') {
                            $sql .= " " . $connector . " object!='UID'";
                            $connector = "and";
                        }
                        #if there are very few propagation points from this letter, reduce the query to only those - building Hlist will be much faster this way
                        if ($p_times < $n) {
                            foreach ($parent_uid[$pl] as $tmp) {
                                $id_value = ereg_replace(letter($tmp), '', $tmp);
                                if ($tC == 'R' && $pl == 'I') {
                                    #when tC is R, it migrates from C and I, but let's not go through it at this point because it takes too long; query bottom up at the subject_id,verb_id,object_id level may be faster
                                    #I know something is wrong with this query to reduce the data, but i don't know waht... problem is that the collections that show up here are only those where user has direct assigned permssion, not the ones that migrate from the project
                                    #$sql .= " ".$connector." ((subject_id = '".$id_value."') or (object_id = '".$id_value."')) ";
                                } else {
                                    $sql .= " " . $connector . " (" . $parent_id . " = '" . $id_value . "') ";
                                }
                                $connector = "or";
                            }
                        }
                        $db->query($sql);
                        if ($timer) {
                            $timer->setMarker('entity query run: ' . $sql);
                        }
                        while ($db->next_record()) {
                            $cols = $GLOBALS['dbstruct'][$GLOBALS['plurals'][$element]];
                            $uid = $tC . $db->f($tn_id);
                            for ($i = 0; $i < count($cols); $i++) {
                                $all_data[$tC][$uid][$cols[$i]] = $db->f($cols[$i]);
                            }
                        }
                    }
                    #also look for children of this p in the permissions table
                    if (!is_array($all_shared[$pl . $tC])) {
                        if ($tC == 'R' && ($pl == 'C' || $pl == 'I')) {
                            #bypass to do bbottom up
                            #echo 'ola';exit;
                        } else {
                            $sqlP = "select shared_with,uid from s3db_permission ";
                            $connector = "where";
                            if ($p_times < $n) {
                                foreach ($parent_uid[$pl] as $tmp) {
                                    $sqlP .= $connector . " (shared_with = '" . $tmp . "') ";
                                    $connector = "or";
                                }
                                $connector = "and";
                            } else {
                                $sqlP .= $connector . " shared_with " . $GLOBALS['regexp'] . " '^" . $pl . "'";
                                $connector = "and";
                            }
                            $sqlP .= " " . $connector . " uid " . $GLOBALS['regexp'] . " '^" . $tC . "'";
                            $sqlP .= " " . $connector . " id not in (" . str_replace("*", $tn_id, $sql) . ")";
                            $db->query($sqlP);
                            if ($timer) {
                                $timer->setMarker('permission query run: ' . $sqlP);
                            }
                            #Since there can only be 1 uid, 1shared_with per row, we can build Hlist right away
                            while ($db->next_record()) {
                                $uid = $db->f('uid');
                                $sw = $db->f('shared_with');
                                #save the data found for general queries
                                if ($p_times > $n) {
                                    $all_shared[$pl . $tC][$sw] = $uid;
                                } else {
                                    if (strlen($sw) > 1) {
                                        if (!is_array($Hlist[$sw])) {
                                            $Hlist[$sw] = array();
                                        }
                                        if (!in_array($uid, $Hlist[$sw])) {
                                            array_push($Hlist[$sw], $uid);
                                            $moreC[] = $uid;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    #now distribute the all shared across parent/child connectors
                    if (is_array($all_shared[$pl . $tC])) {
                        foreach ($all_shared[$pl . $tC] as $sw => $uid) {
                            if (strlen($sw) >= 1) {
                                if (!is_array($Hlist[$sw])) {
                                    $Hlist[$sw] = array();
                                }
                                if (!in_array($uid, $Hlist[$sw])) {
                                    if (in_array(letter($uid), $e_upstream)) {
                                        array_push($Hlist[$sw], $uid);
                                        $moreC[] = $uid;
                                    }
                                }
                            }
                        }
                    }
                    #now redistribute all_data according to the parent being explored
                    if (is_array($all_data[$tC])) {
                        foreach ($all_data[$tC] as $uid => $element_info) {
                            ##a little trick to asusme subject-Id and object_id as collections; verb_id as items;
                            if ($tC == 'R') {
                                if ($pl == 'C') {
                                    $sw = $pl . $element_info['subject_id'];
                                }
                                if ($pl == 'I') {
                                    $sw = $pl . $element_info['verb_id'];
                                }
                            } else {
                                $sw = $pl . $element_info[$parent_id];
                            }
                            #when there is not data for parent (for example, object_id is empty), there is not need to propagate
                            if (strlen($sw) > 1) {
                                if (!is_array($Hlist[$sw])) {
                                    $Hlist[$sw] = array();
                                }
                                if (!in_array($uid, $Hlist[$sw])) {
                                    array_push($Hlist[$sw], $uid);
                                    #is there child data for this element yet?
                                    #if(!($e=='R' && !ereg('^S',$uid))) #because there can be some many items, and rule query should be fast, will not propagate from I to rule, for now...
                                    if (in_array(letter($uid), $e_upstream)) {
                                        $moreC[] = $uid;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        #if all entities were queries, put data in a file to save time next time (but not if only a subset was queried => TO BE COMPLETED
        #And now build the seed that will be used to propagate permissions to the next level
        if (!empty($moreC)) {
            $all_data_file = $GLOBALS['uploads'] . 'alldata_tmp' . rand(100, 200);
            file_put_contents($all_data_file, serialize($all_data));
            if ($timer) {
                $timer->setMarker('Saving data in a file.');
            }
            #save the var in disk
            $Hlist_file = $GLOBALS['uploads'] . 'Hlist' . rand(100, 200);
            file_put_contents($Hlist_file, serialize($Hlist));
            chmod($Hlist_file, 0777);
            #save the shared
            $shared_file = $GLOBALS['uploads'] . 'shared' . rand(100, 200);
            file_put_contents($shared_file, serialize($all_shared));
            chmod($shared_file, 0777);
            $j++;
            $Hlist = top_down_propagation_list($toFind, $moreC, $db, $Hlist_file, $all_data_file, $shared_file, $j);
        }
    }
    return $Hlist;
}