private static function getURIObject($objectURI, $type) { $Types = ucwords($type) . 's'; $types = strtolower($Types); $libraryType = null; $baseURI = self::getBaseURI(); // If not found, try global URI if (strpos($objectURI, $baseURI) !== 0) { throw new Exception("Invalid base URI '{$objectURI}'"); } $objectURI = substr($objectURI, strlen($baseURI)); $typeRE = "/^(users|groups)\\/([0-9]+)(?:\\/|\$)/"; if (!preg_match($typeRE, $objectURI, $matches)) { throw new Exception("Invalid library URI '{$objectURI}'"); } $libraryType = substr($matches[1], 0, -1); $id = $matches[2]; $objectURI = preg_replace($typeRE, '', $objectURI); if ($libraryType == 'user') { if (!Zotero_Users::exists($id)) { return false; } $libraryID = Zotero_Users::getLibraryIDFromUserID($id); } else { if ($libraryType == 'group') { if (!Zotero_Groups::get($id)) { return false; } $libraryID = Zotero_Groups::getLibraryIDFromGroupID($id); } else { throw new Exception("Invalid library type {$libraryType}"); } } if ($type === 'library') { return $libraryID; } else { // TODO: objectID-based URI? if (!preg_match($types . "\\/([A-Z0-9]{8})", $objectURI, $matches)) { throw new Exception("Invalid object URI '{$objectURI}'"); } $objectKey = $matches[1]; return call_user_func(array("Zotero_{$Types}", "getByLibraryAndKey"), $libraryID, $objectKey); } }
protected function setKeyPermissions($keyObj, $accessElement) { foreach ($accessElement as $accessField => $accessVal) { // 'write' is handled below if ($accessField == 'write') { continue; } // Group library access (<access group="23456"/>) if ($accessField == 'group') { // Grant access to all groups if ($accessVal === 0) { $keyObj->setPermission(0, 'group', true); $keyObj->setPermission(0, 'write', $accessElement['write']); } else { $group = Zotero_Groups::get($accessVal); if (!$group) { $this->e400("Group not found"); } if (!$group->hasUser($keyObj->userID)) { $this->e400("User {$this->id} is not a member of group {$group->id}"); } $keyObj->setPermission($group->libraryID, 'library', true); $keyObj->setPermission($group->libraryID, 'write', $accessElement['write']); } } else { $libraryID = Zotero_Users::getLibraryIDFromUserID($keyObj->userID); $keyObj->setPermission($libraryID, $accessField, $accessVal); $keyObj->setPermission($libraryID, 'write', $accessElement['write']); } } }
public static function setUpBeforeClass() { require "include/config.inc.php"; self::$config = $config; self::$config['userLibraryID'] = Zotero_Users::getLibraryIDFromUserID($config['userID']); }
/** * For HTTP Auth and session-based auth, generate blanket user permissions * manually, since there's no key object */ protected function grantUserPermissions($userID) { $this->permissions = new Zotero_Permissions($userID); $libraryID = Zotero_Users::getLibraryIDFromUserID($userID); // Grant user permissions on own library and all groups $this->permissions->setPermission($libraryID, 'library', true); $this->permissions->setPermission($libraryID, 'files', true); $this->permissions->setPermission($libraryID, 'notes', true); $this->permissions->setPermission($libraryID, 'write', true); $this->permissions->setPermission(0, 'library', true); $this->permissions->setPermission(0, 'write', true); }
public static function getByUserID($userID) { $libraryID = Zotero_Users::getLibraryIDFromUserID($userID); return self::getByLibraryID($libraryID); }
private static function getDeletedObjectIDs($userID, $timestamp, $includeAllUserObjects = false) { /* $sql = "SELECT version FROM version WHERE schema='syncdeletelog'"; $syncLogStart = Zotero_DB::valueQuery($sql); if (!$syncLogStart) { throw ('Sync log start time not found'); } */ /* // Last sync time is before start of log if ($lastSyncDate && new Date($syncLogStart * 1000) > $lastSyncDate) { return -1; } */ // Personal library $shardID = Zotero_Shards::getByUserID($userID); $libraryID = Zotero_Users::getLibraryIDFromUserID($userID); $shardLibraryIDs[$shardID] = array($libraryID); // Group libraries if ($includeAllUserObjects) { $groupIDs = Zotero_Groups::getUserGroups($userID); if ($groupIDs) { // Separate groups into shards for querying foreach ($groupIDs as $groupID) { $libraryID = Zotero_Groups::getLibraryIDFromGroupID($groupID); $shardID = Zotero_Shards::getByLibraryID($libraryID); if (!isset($shardLibraryIDs[$shardID])) { $shardLibraryIDs[$shardID] = array(); } $shardLibraryIDs[$shardID][] = $libraryID; } } } // Send query at each shard $rows = array(); foreach ($shardLibraryIDs as $shardID => $libraryIDs) { $sql = "SELECT libraryID, objectType, id, timestamp\n\t\t\t\t\tFROM syncDeleteLogIDs WHERE libraryID IN (" . implode(', ', array_fill(0, sizeOf($libraryIDs), '?')) . ")"; $params = $libraryIDs; if ($timestamp) { // Send any entries from before these were being properly sent if ($timestamp < 1260778500) { $sql .= " AND (timestamp >= FROM_UNIXTIME(?) OR timestamp BETWEEN 1257968068 AND FROM_UNIXTIME(?))"; $params[] = $timestamp; $params[] = 1260778500; } else { $sql .= " AND timestamp >= FROM_UNIXTIME(?)"; $params[] = $timestamp; } } $sql .= " ORDER BY timestamp"; $shardRows = Zotero_DB::query($sql, $params, $shardID); if ($shardRows) { $rows = array_merge($rows, $shardRows); } } if (!$rows) { return false; } $deletedIDs = array('groups' => array()); foreach ($rows as $row) { $type = $row['objectType'] . 's'; $deletedIDs[$type][] = $row['id']; } return $deletedIDs; }
public static function getUserUsage($userID) { $usage = array(); $libraryID = Zotero_Users::getLibraryIDFromUserID($userID); $sql = "SELECT SUM(size) AS bytes FROM storageFileItems\n\t\t\t\tJOIN items USING (itemID) WHERE libraryID=?"; $libraryBytes = Zotero_DB::valueQuery($sql, $libraryID, Zotero_Shards::getByLibraryID($libraryID)); $usage['library'] = round($libraryBytes / 1024 / 1024, 1); $groupBytes = 0; $usage['groups'] = array(); $ownedLibraries = Zotero_Groups::getUserOwnedGroupLibraries($userID); if ($ownedLibraries) { $shardIDs = Zotero_Groups::getUserGroupShards($userID); foreach ($shardIDs as $shardID) { $sql = "SELECT libraryID, SUM(size) AS `bytes` FROM storageFileItems\n\t\t\t\t\t\tJOIN items I USING (itemID)\n\t\t\t\t\t\tWHERE libraryID IN\n\t\t\t\t\t\t(" . implode(', ', array_fill(0, sizeOf($ownedLibraries), '?')) . ")\n\t\t\t\t\t\tGROUP BY libraryID WITH ROLLUP"; $libraries = Zotero_DB::query($sql, $ownedLibraries, $shardID); if ($libraries) { foreach ($libraries as $library) { if ($library['libraryID']) { $usage['groups'][] = array('id' => Zotero_Groups::getGroupIDFromLibraryID($library['libraryID']), 'usage' => round($library['bytes'] / 1024 / 1024, 1)); } else { $groupBytes += $library['bytes']; } } } } } $usage['total'] = round(($libraryBytes + $groupBytes) / 1024 / 1024, 1); return $usage; }
public static function getUserLibraries($userID) { return array_merge(array(Zotero_Users::getLibraryIDFromUserID($userID)), Zotero_Groups::getUserGroupLibraries($userID)); }
public static function isEditable($obj) { $type = static::field('object'); // Only enforce for sync controller for now if (empty($GLOBALS['controller']) || !$GLOBALS['controller'] instanceof SyncController) { return true; } // Make sure user has access privileges to delete $userID = $GLOBALS['controller']->userID; if (!$userID) { return true; } $objectLibraryID = $obj->libraryID; $libraryType = Zotero_Libraries::getType($objectLibraryID); switch ($libraryType) { case 'user': if (!empty($GLOBALS['controller']->userLibraryID)) { $userLibraryID = $GLOBALS['controller']->userLibraryID; } else { $userLibraryID = Zotero_Users::getLibraryIDFromUserID($userID); } if ($objectLibraryID != $userLibraryID) { return false; } return true; case 'group': $groupID = Zotero_Groups::getGroupIDFromLibraryID($objectLibraryID); $group = Zotero_Groups::get($groupID); if (!$group->hasUser($userID) || !$group->userCanEdit($userID)) { return false; } if ($type == 'item' && $obj->isImportedAttachment() && !$group->userCanEditFiles($userID)) { return false; } return true; default: throw new Exception("Unsupported library type '{$libraryType}'"); } }
private function logGroupLibraryRemoval() { $users = $this->getUsers(); $usersByShard = array(); foreach ($users as $userID) { $shardID = Zotero_Shards::getByUserID($userID); if (!isset($usersByShard[$shardID])) { $usersByShard[$shardID] = array(); } $usersByShard[$shardID][] = $userID; } foreach ($usersByShard as $shardID => $userIDs) { // Add to delete log for all group members $sql = "REPLACE INTO syncDeleteLogIDs (libraryID, objectType, id) VALUES "; $params = array(); $sets = array(); foreach ($userIDs as $userID) { $libraryID = Zotero_Users::getLibraryIDFromUserID($userID); $sets[] = "(?,?,?)"; $params = array_merge($params, array($libraryID, 'group', $this->id)); } $sql .= implode(",", $sets); Zotero_DB::query($sql, $params, $shardID); } }
/** * Make sure we have a valid session */ private function sessionCheck() { if (empty($_REQUEST['sessionid'])) { $this->error(403, 'NO_SESSION_ID', "Session ID not provided"); } if (!preg_match('/^[a-f0-9]{32}$/', $_REQUEST['sessionid'])) { $this->error($this->apiVersion >= 9 ? 403 : 500, 'INVALID_SESSION_ID', "Invalid session ID"); } $sessionID = $_REQUEST['sessionid']; $session = Z_Core::$MC->get("syncSession_{$sessionID}"); $userID = $session ? $session['userID'] : null; // TEMP: can switch to just $session $ipAddress = isset($session['ipAddress']) ? $session['ipAddress'] : null; if (!$userID) { $sql = "SELECT userid, (UNIX_TIMESTAMP(NOW())-UNIX_TIMESTAMP(timestamp)) AS age,\n\t\t\t\t\tINET_NTOA(ipAddress) AS ipAddress FROM sessions WHERE sessionID=?"; $session = Zotero_DB::rowQuery($sql, $sessionID); if (!$session) { $this->error($this->apiVersion >= 9 ? 403 : 500, 'INVALID_SESSION_ID', "Invalid session ID"); } if ($session['age'] > $this->sessionLifetime) { $this->error($this->apiVersion >= 9 ? 403 : 500, 'SESSION_TIMED_OUT', "Session timed out"); } $userID = $session['userid']; $ipAddress = $session['ipAddress']; } $updated = Z_Core::$MC->set("syncSession_{$sessionID}", array('sessionID' => $sessionID, 'userID' => $userID, 'ipAddress' => $ipAddress), $this->sessionLifetime - 1200); // Every 20 minutes, update the timestamp in the DB if (!Z_Core::$MC->get("syncSession_" . $sessionID . "_dbUpdated")) { $sql = "UPDATE sessions SET timestamp=NOW() WHERE sessionID=?"; Zotero_DB::query($sql, $sessionID); Z_Core::$MC->set("syncSession_" . $sessionID . "_dbUpdated", true, 1200); } $this->sessionID = $sessionID; $this->userID = $userID; $this->userLibraryID = Zotero_Users::getLibraryIDFromUserID($userID); $this->ipAddress = $ipAddress; }
/** * This should be called after canAccess() */ public function canWrite($libraryID) { if ($this->super) { return true; } if ($libraryID === 0) { return false; } if (!$libraryID) { throw new Exception('libraryID not provided'); } if (!empty($this->permissions[$libraryID]['write'])) { return true; } $libraryType = Zotero_Libraries::getType($libraryID); switch ($libraryType) { case 'user': return false; // Write permissions match key's write access to user library // Write permissions match key's write access to user library case 'publications': $userLibraryID = Zotero_Users::getLibraryIDFromUserID($this->userID); return $this->canWrite($userLibraryID); case 'group': $groupID = Zotero_Groups::getGroupIDFromLibraryID($libraryID); // If key has write access to all groups, grant access if user // has write access to group if (!empty($this->permissions[0]['write'])) { $group = Zotero_Groups::get($groupID); return $group->userCanEdit($this->userID); } return false; default: throw new Exception("Unsupported library type '{$libraryType}'"); } }