public function updateCollaboratorPermission(IShareable $object, AbstractEyeosPrincipal $collaborator, IPermission $permission) { try { if ($object->getId() === null) { throw new EyeNullPointerException('$object ID cannot be null.'); } $handlerClassName = null; foreach (self::getAllShareableObjectsHandlers() as $handler) { if ($handler->checkType($object)) { $handlerClassName = get_class($handler); break; } } if ($handlerClassName === null) { throw new EyeHandlerNotFoundException('Unable to find a ShareableObjectHandler for object of class ' . get_class($object) . '.'); } $owner = $object->getShareOwner(); SecurityManager::getInstance()->checkPermission($object, new SharePermission(array('updatecollaborator'), $collaborator)); //prepare query array $shareInfoQuery = array(self::SHAREINFO_KEY_OWNERID => $owner->getId(), self::SHAREINFO_KEY_SHAREABLEID => $object->getId(), self::SHAREINFO_KEY_COLLABORATORID => $collaborator->getId(), self::SHAREINFO_KEY_PERMISSIONACTIONS => $permission->getActionsAsString(), self::SHAREINFO_KEY_HANDLERCLASSNAME => $handlerClassName); $this->getProvider()->updateShareInfo($owner, $shareInfoQuery); // TODO: we could also add the ShareInfo object containing the old permission as a // "related source" of the event $event = new SharingEvent(new BasicShareInfo($owner, $object, $collaborator, $permission, $handlerClassName)); foreach ($this->listeners as $listener) { $listener->collaboratorPermissionUpdated($event); } } catch (Exception $e) { self::$Logger->warn('Unable to update collaborator ' . $collaborator->getName() . ' permissions for object of class ' . get_class($object) . '.'); if (self::$Logger->isDebugEnabled()) { self::$Logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } throw $e; } }
public function __toString() { return ExceptionStackUtil::getStackTrace($this, false); }
MMapManager::getInstance()->processRequest($request, new MMapResponse()); // Temporary - Should be moved into a function $__endRequestTime = microtime(true); $__endRequestMemory = memory_get_usage(); $logger = Logger::getLogger('root.metrics'); if ($logger->isInfoEnabled()) { $logger->info('Time: ' . sprintf('%01.2f', $__endRequestTime - $__startTime) . 's / Mem.: ' . sprintf('%01.2f', ($__endRequestMemory - $__startMemory) / 1024) . 'KB (Bootstrap Time: ' . sprintf('%01.2f', $__endBootstrapTime - $__startTime) . 's / Mem: ' . sprintf('%01.2f', ($__endBootstrapMemory - $__startMemory) / 1024) . 'KB) [' . $request->getUrl() . ']'); } } catch (Exception $e) { // Log and display the exception that reached this section // (this should normally *not* happen in a fully set-up production environment) // Log with log4php if available if (class_exists('Logger')) { $logger = Logger::getRootLogger(); $logger->fatal('Uncaught exception detected in the root page! It is likely to come from the bootstrap.'); $logger->fatal(ExceptionStackUtil::getStackTrace($e, false)); } echo 'There is an error in this eyeOS installation, please contact the system administrator'; exit; } //shutdown Bootstrap::end(); /* *Changes the current work directory to EYE_ROOT */ function changeCWD() { //since index.php is always below eyeROOT, we can do this instead to be includable from third party code $basedir = dirname(__FILE__) . '/'; //change directory to EYE_ROOT chdir($basedir . REAL_EYE_ROOT);
private static function loadService($service) { try { $servicePath = SERVICES_PATH . '/' . $service . '/'; Bootstrap::load($servicePath . 'interface.php'); $implementationsPath = $servicePath . '/' . IMPLEMENTATIONS_DIR . '/'; $directory = new DirectoryIterator($implementationsPath); foreach ($directory as $fileInfo) { if ($fileInfo->isFile()) { // self::$Logger->debug('Loading service "' . $fileInfo->getFilename() . '"...'); Bootstrap::load($implementationsPath . $fileInfo->getFilename()); } } } catch (Exception $e) { self::$Logger->error('Cannot load service "' . $service . '"'); if (self::$Logger->isDebugEnabled()) { self::$Logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } throw new EyeBootstrapException('Cannot load service "' . $service . '".', 0, $e); } }
public function processRequest(MMapRequest $request, MMapResponse $response, AppExecutionContext $appContext = null) { $status = ob_get_status(); $response->getHeaders()->append('Content-type:text/javascript'); if (isset($status['name']) && $status['name'] != 'ob_gzhandler') { ob_start("ob_gzhandler"); } try { MMapManager::startSession(); if (!$appContext instanceof AppExecutionContext) { $appContext = new AppExecutionContext(); $appContext->initFromRequest($request); } $appDesc = $appContext->getApplicationDescriptor(); // Check if the session has expired only if the application we want to execute is not "init" nor "logout" // FIXME: Not sure this way for checking session is the best here (maybe a flag in the metadata instead?) if ($appDesc->getName() != 'init' && $appDesc->getName() != 'logout') { MMapManager::checkSessionExpiration(); } // Restore parent process if available try { $checknum = (int) $request->getGET('checknum'); $procFather = ProcManager::getInstance()->getProcessByChecknum($checknum); ProcManager::getInstance()->setCurrentProcess($procFather); // Access control is based on current user, contained in the login context of // the current process, so we can only perform security checks when a process // is active. // In case no login context is defined, we can be sure that almost nothing unsafe // will be done, because this element is required in most of the operations. if ($procFather->getLoginContext() !== null) { SecurityManager::getInstance()->checkExecute($appDesc); } } catch (EyeProcException $e) { } // Start process (PHP) $this->startProcess($appContext); // Append necessary scripts and execute JS code (actually, only append it to the $response body) $appDesc->executeJavascript($appContext, $response); } catch (Exception $e) { self::$Logger->error('Uncaught exception while processing request: ' . $request); self::$Logger->error('Exception message: ' . $e->getMessage()); if (self::$Logger->isDebugEnabled()) { self::$Logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } // Special processing on session expiration if ($e instanceof EyeSessionExpiredException) { $controlMessageBodyRenderer = new ControlMessageBodyRenderer(ControlMessageBodyRenderer::TYPE_SESSION_EXPIRED); } else { // Remove incomplete process $proc = $appContext->getProcess(); if ($proc instanceof Process) { try { ProcManager::getInstance()->kill($proc); } catch (Exception $e) { self::$Logger->error('Cannot kill incomplete process: ' . $proc); self::$Logger->error('Exception message: ' . $e->getMessage()); } } $controlMessageBodyRenderer = new ControlMessageBodyRenderer(ControlMessageBodyRenderer::TYPE_EXCEPTION, $e); } // When using qx.io.ScriptLoader on the JS side, no callback proxy is available // to intercept control messages, so we're using a little workaround here by // calling directly eyeos._callbackProxyWithContent() with the exception summary // in argument. $responseContent = $controlMessageBodyRenderer->getRenderedBody(); $response->setBody('eyeos._callbackProxyWithContent(null, null, null, ' . $responseContent . ');'); } $this->handleClientMessageQueue($response); }
private static final function getNextId() { try { $mutex = new MutexCompat(); $mutex->init(LIB_IDGEN_SEMAPHORE_KEY, LIB_IDGEN_CONFIGURATION_PATH . '/idGen.lock'); $mutex->acquire(); if (file_exists(LIB_IDGEN_CONFIGURATION_PATH . '/idGen.txt')) { $id = (string) file_get_contents(LIB_IDGEN_CONFIGURATION_PATH . '/idGen.txt'); if ('' !== $id) { $intVal = hexdec($id); } else { $intVal = 1; } } else { $intVal = 1; } if ($intVal == PHP_INT_MAX) { throw new EyeOverflowException('Cannot generate ID: integer limit reached!'); } $newId = dechex($intVal + 1); file_put_contents(LIB_IDGEN_CONFIGURATION_PATH . '/idGen.txt', $newId); $mutex->release(); unset($mutex); return $newId; } catch (Exception $e) { $logger = Logger::getLogger('system.libs.idGen'); $logger->fatal('Unable to generate eyeID'); $logger->fatal(ExceptionStackUtil::getStackTrace($e, false)); throw $e; } }
public function checkPermission($object, IPermission $perm, LoginContext $context = null) { try { if ($object === null) { throw new EyeNullPointerException('$object cannot be null.'); } if ($perm === null) { throw new EyeNullPointerException('$perm cannot be null.'); } if ($context === null) { $currentProcess = ProcManager::getInstance()->getCurrentProcess(); if ($currentProcess === null) { self::$Logger->warn('Cannot check permission on object of class ' . get_class($object) . ': No current process.'); throw new EyeAccessControlException('Access denied: No current process.'); } $context = $currentProcess->getLoginContext(); if ($context === null) { //self::$Logger->warn('Cannot check permission on object of class ' . get_class($object) . ': No LoginContext found in current process.'); //throw new EyeAccessControlException('Access denied: No LoginContext found in current process.'); self::$Logger->info('Initializing blank login context for permission check on object of class ' . get_class($object) . '.'); $context = new LoginContext('eyeos-login', new Subject()); } } $checker = new SecurityChecker(); $checker->doCheck($object, $perm, $context); } catch (Exception $e) { self::$Logger->error('Cannot perform permission check: ' . $e->getMessage()); if (self::$Logger->isDebugEnabled()) { self::$Logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } throw $e; } }
/** * TODO * * @param mixed $object * @param IPermission $permission * @param LoginContext $context * @return bool TRUE if the handler performed the permission check successfully, FALSE otherwise. * * @throws EyeInvalidArgumentException * @throws EyeUnexpectedValueException * @throws EyeAccessControlException */ public function checkPermission($object, IPermission $permission, LoginContext $context) { if (!$object instanceof IShareable) { throw new EyeInvalidArgumentException('$object must be an IShareable.'); } if ($object->getId(false) === null) { $this->failureException = new EyeHandlerFailureException('$object has no ID and though is probably not currently shared.'); return false; } try { $eyeosUser = $context->getEyeosUser(); } catch (EyeNullPointerException $e) { $this->failureException = new EyeHandlerFailureException('No eyeos user found in login context.'); return false; } // General sharing actions (addCollaborator, removeCollaborator, updateCollaborator) $actions = $permission->getActions(); if (in_array('addcollaborator', $actions) || in_array('removecollaborator', $actions) || in_array('updatecollaborator', $actions)) { // currently, only the owner can perform those actions if ($eyeosUser->getId() != $object->getShareOwner()->getId()) { self::$Logger->info('Access denied to non-owner user ' . $eyeosUser->getName() . ' for actions "' . $permission->getActionsAsString() . '" on object ' . $object->getId() . '.'); throw new EyeAccessControlException('Only the owner of the object can perform that kind of actions (' . $permission->getActionsAsString() . ').'); } self::$Logger->debug('Access granted to owner ' . $eyeosUser->getName() . ' for actions "' . $permission->getActionsAsString() . '" on object ' . $object->getId() . '.'); return true; } // Object-dependant sharing actions try { $shareInfos = SharingManager::getInstance()->getAllShareInfo($object); } catch (Exception $e) { $logger = Logger::getLogger('system.services.Security.ShareableObjectSecurityHandler'); $logger->warn('Cannot retrieve shareinfo on object with ID: ' . $object->getId(false)); if ($logger->isDebugEnabled()) { $logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } else { $logger->warn('Exception message: ' . $e->getMessage()); } $this->failureException = new EyeHandlerFailureException('Cannot retrieve shareinfo on object with ID: ' . $object->getId(false) . ': ' . $e->getMessage()); return false; } foreach ($shareInfos as $shareInfo) { $collaborator = $shareInfo->getCollaborator(); //$collaborator is a group if ($collaborator instanceof IGroup) { // "is the subject in the current login context representative of the group collaborator?" if (in_array($collaborator, $context->getSubject()->getPrincipals())) { if ($shareInfo->getPermissions()->implies($permission)) { return true; } else { throw new EyeAccessControlException('$object permission actions (' . $shareInfo->getPermissions()->getActionsAsString() . ') ' . 'do not imply requested permission (' . $permission->getActionsAsString() . ') for collaborator ' . $eyeosUser->getName() . ''); } } } else { if ($shareInfo->getCollaborator()->getId() == $eyeosUser->getId()) { if ($shareInfo->getPermissions()->implies($permission)) { return true; } else { throw new EyeAccessControlException('$object permission actions (' . $shareInfo->getPermissions()->getActionsAsString() . ') ' . 'do not imply requested permission (' . $permission->getActionsAsString() . ') for collaborator ' . $eyeosUser->getName() . ''); } } } } // No matching collaborator found => this module is not applicable to the current check => set it as FAILED $this->failureException = new EyeHandlerFailureException('No matching collaborator found for object with ID ' . $object->getId(false) . '.'); return false; }
public function listen($manager) { $userId = ProcManager::getInstance()->getCurrentProcess()->getLoginContext()->getEyeosUser()->getId(); $username = ProcManager::getInstance()->getCurrentProcess()->getLoginContext()->getEyeosUser()->getName(); $subscriptionProvider = new SqlSubscriptionProvider(); if ($subscriptionProvider->getSubscriptions($userId) == false) { /** * User try to listen message, but for same reason (connection problem, logout) * netSync delete subscriptions to this user. * * Stop LongPolling and notify client */ echo "forceRefresh"; exit; } //$myPressence = new Pressence(); //$myPressence->markOnline($username, $manager); session_write_close(); set_time_limit(0); ignore_user_abort(1); header('Cache-Control: no-cache, must-revalidate'); header('Content-type: application/json'); $Logger = Logger::getLogger('system.Frameworks.EyeosModules.NetSync'); //one of every 20 loops, will update the pressence time //but the first one, should do it ever $loop = 20; while (1) { try { echo "\n"; ob_flush(); flush(); if (connection_status() != CONNECTION_NORMAL) { //Maybe user gone offline sleep(35); //Check if user is still connected if (!$subscriptionProvider->isUserConnected($userId)) { // if not notify to all contacts $contacts = PeopleController::getInstance()->getAllContacts($userId); $ids = array(); $myCometSender = new CometSenderLongPolling(); foreach ($contacts as $contact) { $id = $contact->getRelation()->getSourceId(); if ($id == $userId) { $id = $contact->getRelation()->getTargetId(); } $message = new NetSyncMessage('status', 'offline', $id, $userId); //TODO24 ultra hardcoded, we need some kind of php listeners here! $myCometSender->send($message); } shell_exec('rm -rf ' . escapeshellarg(EYE_ROOT . '/' . USERS_DIR . '/' . utf8_basename($username) . '/files/.office/')); $subscriptionProvider->removeAllSubscriptions($userId); } exit; } if ($loop == 20) { $mySubscriptionProvider = new SqlSubscriptionProvider(); $mySubscriptionProvider->refreshPressence($userId); $loop = 0; } else { $loop++; } $mySubscriptionProvider = new SqlSubscriptionProvider(); $channels = $mySubscriptionProvider->getSubscriptions($userId); $messageProvider = new CometSqlMessageProvider(); if (is_array($channels)) { $messages = $messageProvider->read($channels, $userId, $this->lastId); if (is_array($messages) && count($messages) > 0) { @session_start(); usort($messages, "customMessageComparation"); $_SESSION['comet']['lastid'] = $messages[count($messages) - 1]['id']; //$Logger->debug("last message id: " . $_SESSION['comet']['lastid']); //@todo use pseudo-random-related-to-tableid or something as transaction ID, no a id of table return $messages; } } sleep(1); } catch (Exception $e) { $logger = Logger::getLogger('netsync'); $logger->fatal('Exception in netsync!'); $logger->fatal(ExceptionStackUtil::getStackTrace($e, false)); exit; } } }
private function renderResponse(MMapResponse $response) { if (!$response->isValid()) { if (self::$Logger->isInfoEnabled()) { self::$Logger->info('Skipping invalid response: ' . $response); } return; } try { // headers foreach ($response->getHeaders() as $headerField) { self::$Logger->info($headerField); if (is_array($headerField)) { if (isset($headerField[1])) { if (isset($headerField[2])) { header($headerField[0], $headerField[1], $headerField[2]); } else { header($headerField[0], $headerField[1]); } } else { header($headerField[0]); } } else { //if ( !ob_get_status() ) { header($headerField); //} } } // body $bodyRenderer = $response->getBodyRenderer(); if ($bodyRenderer !== null) { self::$Logger->info('Using BodyRenderer: ' . $bodyRenderer); $bodyRenderer->doRender(); } else { self::$Logger->info('Using raw body'); echo $response->getBody(); } } catch (Exception $e) { self::$Logger->error('Exception caught while rendering response!'); self::$Logger->error('Exception message: ' . $e->getMessage()); if (self::$Logger->isDebugEnabled()) { self::$Logger->debug(ExceptionStackUtil::getStackTrace($e, false)); self::$Logger->debug((string) $response); } // the exception will be finally caught by the general try/catch block in index.php throw $e; } }
public function updateTag(ITag $tag, ITag $newTag) { SecurityManager::getInstance()->checkPermission($tag, new SimplePermission(null, array('update'))); try { $this->getProvider()->updateTag($tag, $newTag); } catch (Exception $e) { self::$Logger->error('Unable to update tag "' . $tag . '": ' . $e->getMessage()); if (self::$Logger->isDebugEnabled()) { self::$Logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } throw $e; } }
/** * Kill a process, and remove it from the process table. * * @param Process $proc the process to be killed, the attribute <b>pid</b> should be filled with the process pid to kill * @throws EyeInvalidArgumentException If the arguments are incorrect * @throws EyeProcException If there is no such process with the given pid */ public function kill(Process $proc) { try { $processTable = $this->getProcessesTable(); $pid = $proc->getPid(); if (!isset($processTable[$pid])) { throw new EyeProcException('Process $proc with PID ' . $pid . ' not found.'); } SecurityManager::getInstance()->checkPermission($proc, new SimplePermission('', array('kill'))); unset($processTable[$pid]); Kernel::enterSystemMode(); $this->memoryManager->set('processTable', $processTable); Kernel::exitSystemMode(); if ($this->currentProcess->getPid() == $pid) { $this->currentProcess = null; } $this->logger->debug('Process killed: ' . $proc); $this->fireEvent('processKilled', new ProcEvent($proc)); } catch (Exception $e) { $this->logger->warn('Error killing process: ' . $proc . ' (' . $e->getMessage() . ')'); if ($this->logger->isDebugEnabled()) { $this->logger->debug(ExceptionStackUtil::getStackTrace($e, false)); } throw $e; } }