/** * Writes single cache record into DB. * * @param string $key Cache key name * @param mxied $data Serialized cache data * * @param boolean True on success, False on failure */ private function write_record($key, $data) { if (!$this->db) { return false; } if ($this->type == 'memcache' || $this->type == 'apc') { return $this->add_record($this->ckey($key), $data); } $key_exists = array_key_exists($key, $this->cache_sums); $key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $this->db->query("DELETE FROM " . $this->table . " WHERE user_id = ?" . " AND cache_key = ?", $this->userid, $key); return true; } // update existing cache record if ($key_exists) { $result = $this->db->query("UPDATE " . $this->table . " SET created = " . $this->db->now() . ", expires = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", data = ?" . " WHERE user_id = ?" . " AND cache_key = ?", $data, $this->userid, $key); } else { // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query("INSERT INTO " . $this->table . " (created, expires, user_id, cache_key, data)" . " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?, ?)", $this->userid, $key, $data); } return $this->db->affected_rows($result); }
/** * Writes single cache record into DB. * * @param string $key Cache key name * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ private function write_record($key, $data) { if (!$this->db) { return false; } // don't attempt to write too big data sets if (strlen($data) > $this->max_packet_size()) { trigger_error("rcube_cache: max_packet_size ({$this->max_packet}) exceeded for key {$key}. Tried to write " . strlen($data) . " bytes", E_USER_WARNING); return false; } if ($this->type == 'memcache' || $this->type == 'apc') { return $this->add_record($this->ckey($key), $data); } $key_exists = array_key_exists($key, $this->cache_sums); $key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $this->db->query("DELETE FROM {$this->table} WHERE `cache_key` = ?", $key); return true; } // update existing cache record if ($key_exists) { $result = $this->db->query("UPDATE {$this->table}" . " SET `created` = " . $this->db->now() . ", `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", `data` = ?" . " WHERE `cache_key` = ?", $data, $key); } else { // for better performance we allow more records for one key // so, no need to check if record exist (see rcube_cache::read_record()) $result = $this->db->query("INSERT INTO {$this->table}" . " (`created`, `expires`, `cache_key`, `data`)" . " VALUES (" . $this->db->now() . ", " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . ", ?, ?)", $key, $data); } return $this->db->affected_rows($result); }
/** * Writes single cache record into DB. * * @param string $key Cache key name * @param mixed $data Serialized cache data * * @param boolean True on success, False on failure */ private function write_record($key, $data) { if (!$this->db) { return false; } // don't attempt to write too big data sets if (strlen($data) > $this->max_packet_size()) { trigger_error("rcube_cache: max_packet_size ({$this->max_packet}) exceeded for key {$key}. Tried to write " . strlen($data) . " bytes", E_USER_WARNING); return false; } if ($this->type == 'memcache' || $this->type == 'apc') { $result = $this->add_record($this->ckey($key), $data); // make sure index will be updated if ($result) { if (!array_key_exists($key, $this->cache_sums)) { $this->cache_sums[$key] = true; } $this->load_index(); if (!$this->index_changed && !in_array($key, $this->index)) { $this->index_changed = true; } } return $result; } $db_key = $this->prefix . '.' . $key; // Remove NULL rows (here we don't need to check if the record exist) if ($data == 'N;') { $result = $this->db->query("DELETE FROM {$this->table} WHERE `cache_key` = ?", $db_key); return !$this->db->is_error($result); } $key_exists = array_key_exists($key, $this->cache_sums); $expires = $this->ttl ? $this->db->now($this->ttl) : 'NULL'; if (!$key_exists) { // Try INSERT temporarily ignoring "duplicate key" errors $this->db->set_option('ignore_key_errors', true); $result = $this->db->query("INSERT INTO {$this->table} (`expires`, `cache_key`, `data`)" . " VALUES ({$expires}, ?, ?)", $db_key, $data); $this->db->set_option('ignore_key_errors', false); } // otherwise try UPDATE if (!isset($result) || !($count = $this->db->affected_rows($result))) { $result = $this->db->query("UPDATE {$this->table} SET `expires` = {$expires}, `data` = ?" . " WHERE `cache_key` = ?", $data, $db_key); $count = $this->db->affected_rows($result); } return $count > 0; }
/** * Add the given contact records the a certain group * * @param string Group identifier * @param array List of contact identifiers to be added * @return int Number of contacts added */ function add_to_group($group_id, $ids) { if (!is_array($ids)) { $ids = explode(self::SEPARATOR, $ids); } $added = 0; $exists = array(); // get existing assignments ... $sql_result = $this->db->query("SELECT contact_id FROM " . $this->db->table_name($this->db_groupmembers) . " WHERE contactgroup_id=?" . " AND contact_id IN (" . $this->db->array2list($ids, 'integer') . ")", $group_id); while ($sql_result && ($sql_arr = $this->db->fetch_assoc($sql_result))) { $exists[] = $sql_arr['contact_id']; } // ... and remove them from the list $ids = array_diff($ids, $exists); foreach ($ids as $contact_id) { $this->db->query("INSERT INTO " . $this->db->table_name($this->db_groupmembers) . " (contactgroup_id, contact_id, created)" . " VALUES (?, ?, " . $this->db->now() . ")", $group_id, $contact_id); if ($error = $this->db->is_error()) { $this->set_error(self::ERROR_SAVING, $error); } else { $added++; } } return $added; }
/** * Synchronizes the mailbox. * * @param string $mailbox Folder name */ function synchronize($mailbox) { // RFC4549: Synchronization Operations for Disconnected IMAP4 Clients // RFC4551: IMAP Extension for Conditional STORE Operation // or Quick Flag Changes Resynchronization // RFC5162: IMAP Extensions for Quick Mailbox Resynchronization // @TODO: synchronize with other methods? $qresync = $this->imap->get_capability('QRESYNC'); $condstore = $qresync ? true : $this->imap->get_capability('CONDSTORE'); if (!$qresync && !$condstore) { return; } // Get stored index $index = $this->get_index_row($mailbox); // database is empty if (empty($index)) { // set the flag that DB was already queried for index // this way we'll be able to skip one SELECT in get_index() $this->icache[$mailbox]['index_queried'] = true; return; } $this->icache[$mailbox]['index'] = $index; // no last HIGHESTMODSEQ value if (empty($index['modseq'])) { return; } if (!$this->imap->check_connection()) { return; } // Enable QRESYNC $res = $this->imap->conn->enable($qresync ? 'QRESYNC' : 'CONDSTORE'); if ($res === false) { return; } // Close mailbox if already selected to get most recent data if ($this->imap->conn->selected == $mailbox) { $this->imap->conn->close(); } // Get mailbox data (UIDVALIDITY, HIGHESTMODSEQ, counters, etc.) $mbox_data = $this->imap->folder_data($mailbox); if (empty($mbox_data)) { return; } // Check UIDVALIDITY if ($index['validity'] != $mbox_data['UIDVALIDITY']) { $this->clear($mailbox); return; } // QRESYNC not supported on specified mailbox if (!empty($mbox_data['NOMODSEQ']) || empty($mbox_data['HIGHESTMODSEQ'])) { return; } // Nothing new if ($mbox_data['HIGHESTMODSEQ'] == $index['modseq']) { return; } $uids = array(); $removed = array(); // Get known UIDs if ($this->mode & self::MODE_MESSAGE) { $sql_result = $this->db->query("SELECT `uid`" . " FROM {$this->messages_table}" . " WHERE `user_id` = ?" . " AND `mailbox` = ?", $this->userid, $mailbox); while ($sql_arr = $this->db->fetch_assoc($sql_result)) { $uids[] = $sql_arr['uid']; } } // Synchronize messages data if (!empty($uids)) { // Get modified flags and vanished messages // UID FETCH 1:* (FLAGS) (CHANGEDSINCE 0123456789 VANISHED) $result = $this->imap->conn->fetch($mailbox, $uids, true, array('FLAGS'), $index['modseq'], $qresync); if (!empty($result)) { foreach ($result as $msg) { $uid = $msg->uid; // Remove deleted message if ($this->skip_deleted && !empty($msg->flags['DELETED'])) { $removed[] = $uid; // Invalidate index $index['valid'] = false; continue; } $flags = 0; if (!empty($msg->flags)) { foreach ($this->flags as $idx => $flag) { if (!empty($msg->flags[$flag])) { $flags += $idx; } } } $this->db->query("UPDATE {$this->messages_table}" . " SET `flags` = ?, `expires` = " . ($this->ttl ? $this->db->now($this->ttl) : 'NULL') . " WHERE `user_id` = ?" . " AND `mailbox` = ?" . " AND `uid` = ?" . " AND `flags` <> ?", $flags, $this->userid, $mailbox, $uid, $flags); } } // VANISHED found? if ($qresync) { $mbox_data = $this->imap->folder_data($mailbox); // Removed messages found $uids = rcube_imap_generic::uncompressMessageSet($mbox_data['VANISHED']); if (!empty($uids)) { $removed = array_merge($removed, $uids); // Invalidate index $index['valid'] = false; } } // remove messages from database if (!empty($removed)) { $this->remove_message($mailbox, $removed); } } $sort_field = $index['sort_field']; $sort_order = $index['object']->get_parameters('ORDER'); $exists = true; // Validate index if (!$this->validate($mailbox, $index, $exists)) { // Invalidate (remove) thread index // if $exists=false it was already removed in validate() if ($exists) { $this->remove_thread($mailbox); } // Update index $data = $this->get_index_data($mailbox, $sort_field, $sort_order, $mbox_data); } else { $data = $index['object']; } // update index and/or HIGHESTMODSEQ value $this->add_index_row($mailbox, $sort_field, $data, $mbox_data, $exists); // update internal cache for get_index() $this->icache[$mailbox]['index']['object'] = $data; }
/** * Update user's last_login timestamp */ function touch() { if ($this->ID) { $this->db->query("UPDATE " . $this->db->table_name('users') . " SET last_login = "******" WHERE user_id = ?", $this->ID); } }
/** * Update user's last_login timestamp */ function touch() { if ($this->ID) { $this->db->query("UPDATE " . $this->db->table_name('users', true) . " SET `last_login` = " . $this->db->now() . " WHERE `user_id` = ?", $this->ID); } }