<commit_before><?php
/***********************************************
* File      :   asdevice.php
* Project   :   Z-Push
* Descr     :   The ASDevice holds basic data about a device,
*               its users and the linked states
*
* Created   :   11.04.2011
*
* Copyright 2007 - 2016 Zarafa Deutschland GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Consult LICENSE file for details
************************************************/

class ASDevice extends StateObject {
    const UNDEFINED = -1;
    // content data
    const FOLDERUUID = 1;
    const FOLDERTYPE = 2;
    const FOLDERSUPPORTEDFIELDS = 3;
    const FOLDERSYNCSTATUS = 4;
    const FOLDERBACKENDID = 5;
    const DEFAULTPOLICYNAME = 'default';

    // expected values for not set member variables
    protected $unsetdata = array(
                                    'useragenthistory' => array(),
                                    'hierarchyuuid' => false,
                                    'contentdata' => array(),
                                    'wipestatus' => SYNC_PROVISION_RWSTATUS_NA,
                                    'wiperequestedby' => false,
                                    'wiperequestedon' => false,
                                    'wipeactionon' => false,
                                    'lastupdatetime' => 0,
                                    'conversationmode' => false,
                                    'policyhash' => false,
                                    'policyname' => self::DEFAULTPOLICYNAME,
                                    'policykey' => self::UNDEFINED,
                                    'forcesave' => false,
                                    'asversion' => false,
                                    'ignoredmessages' => array(),
                                    'announcedASversion' => false,
                                    'foldersynccomplete' => true,
                                    'additionalfolders' => array(),
                                    'koeversion' => false,
                                    'koebuild' => false,
                                    'koebuilddate' => false,
                                    'koegabbackendfolderid' => false,
                                    'koecapabilities' => array(),
                                );

    static private $loadedData;
    protected $newdevice;
    protected $hierarchyCache;
    protected $ignoredMessageIds;
    protected $backend2folderidCache;

    /**
     * AS Device constructor
     *
     * @param string        $devid
     * @param string        $devicetype
     * @param string        $getuser
     * @param string        $useragent
     *
     * @access public
     * @return
     */
    public function __construct($devid, $devicetype, $getuser, $useragent) {
        $this->deviceid = $devid;
        $this->devicetype = $devicetype;
        list ($this->deviceuser, $this->domain) =  Utils::SplitDomainUser($getuser);
        $this->useragent = $useragent;
        $this->firstsynctime = time();
        $this->newdevice = true;
        $this->ignoredMessageIds = array();
        $this->backend2folderidCache = false;
    }

    /**
     * initializes the ASDevice with previousily saved data
     *
     * @param mixed     $stateObject        the StateObject containing the device data
     * @param boolean   $semanticUpdate     indicates if data relevant for all users should be cross checked (e.g. wipe requests)
     *
     * @access public
     * @return
     */
    public function SetData($stateObject, $semanticUpdate = true) {
        if (!($stateObject instanceof StateObject) || !isset($stateObject->devices) || !is_array($stateObject->devices)) return;

        // is information about this device & user available?
        if (isset($stateObject->devices[$this->deviceuser]) && $stateObject->devices[$this->deviceuser] instanceof ASDevice) {
            // overwrite local data with data from the saved object
            $this->SetDataArray($stateObject->devices[$this->deviceuser]->GetDataArray());
            $this->newdevice = false;
            ZLog::Write(LOGLEVEL_DEBUG, sprintf("ASDevice data loaded for user: '%s'", $this->deviceuser));
        }

        // check if RWStatus from another user on same device may require action
        if ($semanticUpdate && count($stateObject->devices) > 1) {
            foreach ($stateObject->devices as $user=>$asuserdata) {
                if ($user == $this->user) continue;

                // another user has a required action on this device
                if (isset($asuserdata->wipeStatus) && $asuserdata->wipeStatus > SYNC_PROVISION_RWSTATUS_OK) {
                    ZLog::Write(LOGLEVEL_INFO, sprintf("User '%s' has requested a remote wipe for this device on '%s'", $asuserdata->wipeRequestBy, strftime("%Y-%m-%d %H:%M", $asuserdata->wipeRequstOn)));

                    // reset status to PENDING if wipe was executed before
                    $this->wipeStatus =  ($asuserdata->wipeStatus & SYNC_PROVISION_RWSTATUS_WIPED)?SYNC_PROVISION_RWSTATUS_PENDING:$asuserdata->wipeStatus;
                    $this->wipeRequestBy =  $asuserdata->wipeRequestBy;
                    $this->wipeRequestOn =  $asuserdata->wipeRequestOn;
                    $this->wipeActionOn = $asuserdata->wipeActionOn;
                    break;
                }
            }
        }

        self::$loadedData = $stateObject;
        $this->changed = false;
    }

    /**
     * Returns the current AS Device in it's StateObject
     * If the data was not changed, it returns false (no need to update any data)
     *
     * @access public
     * @return array/boolean
     */
    public function GetData() {
        if (! $this->changed)
            return false;

        // device was updated
        $this->lastupdatetime = time();
        unset($this->ignoredMessageIds);
        unset($this->backend2folderidCache);

        if (!isset(self::$loadedData) || !isset(self::$loadedData->devices) || !is_array(self::$loadedData->devices)) {
            self::$loadedData = new StateObject();
            $devices = array();
        }
        else
            $devices = self::$loadedData->devices;

        $devices[$this->deviceuser] = $this;

        // check if RWStatus has to be updated so it can be updated for other users on same device
        if (isset($this->wipeStatus) && $this->wipeStatus > SYNC_PROVISION_RWSTATUS_OK) {
            foreach ($devices as $user=>$asuserdata) {
                if ($user == $this->deviceuser) continue;
                if (isset($this->wipeStatus))       $asuserdata->wipeStatus     = $this->wipeStatus;
                if (isset($this->wipeRequestBy))    $asuserdata->wipeRequestBy  = $this->wipeRequestBy;
                if (isset($this->wipeRequestOn))    $asuserdata->wipeRequestOn  = $this->wipeRequestOn;
                if (isset($this->wipeActionOn))     $asuserdata->wipeActionOn   = $this->wipeActionOn;
                $devices[$user] = $asuserdata;

                ZLog::Write(LOGLEVEL_DEBUG, sprintf("Updated remote wipe status for user '%s' on the same device", $user));
            }
        }
        self::$loadedData->devices = $devices;
        return self::$loadedData;
    }

   /**
     * Removes internal data from the object, so this data can not be exposed.
     *
     * @param boolean $stripHierarchyCache  (opt) strips the hierarchy cache - default: true
     *
     * @access public
     * @return boolean
     */
    public function StripData($stripHierarchyCache = true) {
        unset($this->changed);
        unset($this->unsetdata);
        unset($this->forceSave);
        unset($this->newdevice);
        unset($this->ignoredMessageIds);
        unset($this->backend2folderidCache);

        if (isset($this->ignoredmessages) && is_array($this->ignoredmessages)) {
            $imessages = $this->ignoredmessages;
            $unserializedMessage = array();
            foreach ($imessages as $im) {
                $im->asobject = unserialize($im->asobject);
                $im->asobject->StripData();<commit_msg>ZP-1256 Set backend2folderidCache of ASDevice to false, so it can be rebuilt.<commit_after><?php
/***********************************************
* File      :   asdevice.php
* Project   :   Z-Push
* Descr     :   The ASDevice holds basic data about a device,
*               its users and the linked states
*
* Created   :   11.04.2011
*
* Copyright 2007 - 2016 Zarafa Deutschland GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* Consult LICENSE file for details
************************************************/

class ASDevice extends StateObject {
    const UNDEFINED = -1;
    // content data
    const FOLDERUUID = 1;
    const FOLDERTYPE = 2;
    const FOLDERSUPPORTEDFIELDS = 3;
    const FOLDERSYNCSTATUS = 4;
    const FOLDERBACKENDID = 5;
    const DEFAULTPOLICYNAME = 'default';

    // expected values for not set member variables
    protected $unsetdata = array(
                                    'useragenthistory' => array(),
                                    'hierarchyuuid' => false,
                                    'contentdata' => array(),
                                    'wipestatus' => SYNC_PROVISION_RWSTATUS_NA,
                                    'wiperequestedby' => false,
                                    'wiperequestedon' => false,
                                    'wipeactionon' => false,
                                    'lastupdatetime' => 0,
                                    'conversationmode' => false,
                                    'policyhash' => false,
                                    'policyname' => self::DEFAULTPOLICYNAME,
                                    'policykey' => self::UNDEFINED,
                                    'forcesave' => false,
                                    'asversion' => false,
                                    'ignoredmessages' => array(),
                                    'announcedASversion' => false,
                                    'foldersynccomplete' => true,
                                    'additionalfolders' => array(),
                                    'koeversion' => false,
                                    'koebuild' => false,
                                    'koebuilddate' => false,
                                    'koegabbackendfolderid' => false,
                                    'koecapabilities' => array(),
                                );

    static private $loadedData;
    protected $newdevice;
    protected $hierarchyCache;
    protected $ignoredMessageIds;
    protected $backend2folderidCache;

    /**
     * AS Device constructor
     *
     * @param string        $devid
     * @param string        $devicetype
     * @param string        $getuser
     * @param string        $useragent
     *
     * @access public
     * @return
     */
    public function __construct($devid, $devicetype, $getuser, $useragent) {
        $this->deviceid = $devid;
        $this->devicetype = $devicetype;
        list ($this->deviceuser, $this->domain) =  Utils::SplitDomainUser($getuser);
        $this->useragent = $useragent;
        $this->firstsynctime = time();
        $this->newdevice = true;
        $this->ignoredMessageIds = array();
        $this->backend2folderidCache = false;
    }

    /**
     * initializes the ASDevice with previousily saved data
     *
     * @param mixed     $stateObject        the StateObject containing the device data
     * @param boolean   $semanticUpdate     indicates if data relevant for all users should be cross checked (e.g. wipe requests)
     *
     * @access public
     * @return
     */
    public function SetData($stateObject, $semanticUpdate = true) {
        if (!($stateObject instanceof StateObject) || !isset($stateObject->devices) || !is_array($stateObject->devices)) return;

        // is information about this device & user available?
        if (isset($stateObject->devices[$this->deviceuser]) && $stateObject->devices[$this->deviceuser] instanceof ASDevice) {
            // overwrite local data with data from the saved object
            $this->SetDataArray($stateObject->devices[$this->deviceuser]->GetDataArray());
            $this->newdevice = false;
            ZLog::Write(LOGLEVEL_DEBUG, sprintf("ASDevice data loaded for user: '%s'", $this->deviceuser));
        }

        // check if RWStatus from another user on same device may require action
        if ($semanticUpdate && count($stateObject->devices) > 1) {
            foreach ($stateObject->devices as $user=>$asuserdata) {
                if ($user == $this->user) continue;

                // another user has a required action on this device
                if (isset($asuserdata->wipeStatus) && $asuserdata->wipeStatus > SYNC_PROVISION_RWSTATUS_OK) {
                    ZLog::Write(LOGLEVEL_INFO, sprintf("User '%s' has requested a remote wipe for this device on '%s'", $asuserdata->wipeRequestBy, strftime("%Y-%m-%d %H:%M", $asuserdata->wipeRequstOn)));

                    // reset status to PENDING if wipe was executed before
                    $this->wipeStatus =  ($asuserdata->wipeStatus & SYNC_PROVISION_RWSTATUS_WIPED)?SYNC_PROVISION_RWSTATUS_PENDING:$asuserdata->wipeStatus;
                    $this->wipeRequestBy =  $asuserdata->wipeRequestBy;
                    $this->wipeRequestOn =  $asuserdata->wipeRequestOn;
                    $this->wipeActionOn = $asuserdata->wipeActionOn;
                    break;
                }
            }
        }

        self::$loadedData = $stateObject;
        $this->changed = false;
    }

    /**
     * Returns the current AS Device in it's StateObject
     * If the data was not changed, it returns false (no need to update any data)
     *
     * @access public
     * @return array/boolean
     */
    public function GetData() {
        if (! $this->changed)
            return false;

        // device was updated
        $this->lastupdatetime = time();
        unset($this->ignoredMessageIds);
        unset($this->backend2folderidCache);

        if (!isset(self::$loadedData) || !isset(self::$loadedData->devices) || !is_array(self::$loadedData->devices)) {
            self::$loadedData = new StateObject();
            $devices = array();
        }
        else
            $devices = self::$loadedData->devices;

        $devices[$this->deviceuser] = $this;

        // check if RWStatus has to be updated so it can be updated for other users on same device
        if (isset($this->wipeStatus) && $this->wipeStatus > SYNC_PROVISION_RWSTATUS_OK) {
            foreach ($devices as $user=>$asuserdata) {
                if ($user == $this->deviceuser) continue;
                if (isset($this->wipeStatus))       $asuserdata->wipeStatus     = $this->wipeStatus;
                if (isset($this->wipeRequestBy))    $asuserdata->wipeRequestBy  = $this->wipeRequestBy;
                if (isset($this->wipeRequestOn))    $asuserdata->wipeRequestOn  = $this->wipeRequestOn;
                if (isset($this->wipeActionOn))     $asuserdata->wipeActionOn   = $this->wipeActionOn;
                $devices[$user] = $asuserdata;

                ZLog::Write(LOGLEVEL_DEBUG, sprintf("Updated remote wipe status for user '%s' on the same device", $user));
            }
        }
        self::$loadedData->devices = $devices;
        return self::$loadedData;
    }

   /**
     * Removes internal data from the object, so this data can not be exposed.
     *
     * @param boolean $stripHierarchyCache  (opt) strips the hierarchy cache - default: true
     *
     * @access public
     * @return boolean
     */
    public function StripData($stripHierarchyCache = true) {
        unset($this->changed);
        unset($this->unsetdata);
        unset($this->forceSave);
        unset($this->newdevice);
        unset($this->ignoredMessageIds);
        $this->backend2folderidCache = false;

        if (isset($this->ignoredmessages) && is_array($this->ignoredmessages)) {
            $imessages = $this->ignoredmessages;
            $unserializedMessage = array();
            foreach ($imessages as $im) {
                $im->asobject = unserialize($im->asobject);
                $im->asobject->StripData();
{'fraction_non_alphanumeric': 0.11846569670481338, 'fraction_numerical': 0.003622980044855943, 'mean_word_length': 1.9187646861362873, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 211, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '782617', 'n_tokens_mistral': 4672, 'n_tokens_neox': 4522, 'n_words': 1187}