|
|
|
@ -16,7 +16,6 @@ use \OCP\IRequest;
|
|
|
|
|
use \OCP\AppFramework\Http;
|
|
|
|
|
use \OCP\AppFramework\Http\JSONResponse;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use \OCA\Documents\Db;
|
|
|
|
|
use \OCA\Documents\File;
|
|
|
|
|
use \OCA\Documents\Helper;
|
|
|
|
@ -40,6 +39,7 @@ class SessionController extends Controller{
|
|
|
|
|
|
|
|
|
|
protected $uid;
|
|
|
|
|
protected $logger;
|
|
|
|
|
protected $shareToken;
|
|
|
|
|
|
|
|
|
|
public function __construct($appName, IRequest $request, $logger, $uid){
|
|
|
|
|
parent::__construct($appName, $request);
|
|
|
|
@ -62,13 +62,11 @@ class SessionController extends Controller{
|
|
|
|
|
|
|
|
|
|
$response = array_merge(
|
|
|
|
|
Db\Session::start($uid, $file),
|
|
|
|
|
array('status'=>'success')
|
|
|
|
|
[ 'status'=>'success' ]
|
|
|
|
|
);
|
|
|
|
|
} catch (\Exception $e){
|
|
|
|
|
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), array('app' => $this->appName));
|
|
|
|
|
$response = array (
|
|
|
|
|
'status'=>'error'
|
|
|
|
|
);
|
|
|
|
|
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), ['app' => $this->appName]);
|
|
|
|
|
$response = [ 'status'=>'error' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $response;
|
|
|
|
@ -76,8 +74,27 @@ class SessionController extends Controller{
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @NoAdminRequired
|
|
|
|
|
* @PublicPage
|
|
|
|
|
*/
|
|
|
|
|
public function pollAsGuest($command, $args){
|
|
|
|
|
$this->shareToken = $this->request->getParam('token');
|
|
|
|
|
return $this->poll($command, $args);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Store the document content to its origin
|
|
|
|
|
* @NoAdminRequired
|
|
|
|
|
* @PublicPage
|
|
|
|
|
*/
|
|
|
|
|
public function joinAsUser($fileId){
|
|
|
|
|
public function saveAsGuest(){
|
|
|
|
|
$this->shareToken = $this->request->getParam('token');
|
|
|
|
|
return $this->save();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @NoAdminRequired
|
|
|
|
|
*/
|
|
|
|
|
public function join($fileId){
|
|
|
|
|
try {
|
|
|
|
|
$view = \OC\Files\Filesystem::getView();
|
|
|
|
|
$path = $view->getPath($fileId);
|
|
|
|
@ -87,20 +104,18 @@ class SessionController extends Controller{
|
|
|
|
|
$response = Db\Session::start($this->uid, $file);
|
|
|
|
|
} else {
|
|
|
|
|
$info = $view->getFileInfo($path);
|
|
|
|
|
$response = array(
|
|
|
|
|
$response = [
|
|
|
|
|
'permissions' => $info['permissions'],
|
|
|
|
|
'id' => $fileId
|
|
|
|
|
);
|
|
|
|
|
];
|
|
|
|
|
}
|
|
|
|
|
$response = array_merge(
|
|
|
|
|
$response,
|
|
|
|
|
array('status'=>'success')
|
|
|
|
|
[ 'status'=>'success' ]
|
|
|
|
|
);
|
|
|
|
|
} catch (\Exception $e){
|
|
|
|
|
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), array('app' => $this->appName));
|
|
|
|
|
$response = array (
|
|
|
|
|
'status'=>'error'
|
|
|
|
|
);
|
|
|
|
|
$this->logger->warning('Starting a session failed. Reason: ' . $e->getMessage(), [ 'app' => $this->appName ]);
|
|
|
|
|
$response = [ 'status'=>'error' ];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $response;
|
|
|
|
@ -108,41 +123,24 @@ class SessionController extends Controller{
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @NoAdminRequired
|
|
|
|
|
* @PublicPage
|
|
|
|
|
*/
|
|
|
|
|
public function poll($command, $args){
|
|
|
|
|
$response = new JSONResponse();
|
|
|
|
|
|
|
|
|
|
try{
|
|
|
|
|
$esId = isset($args['es_id']) ? $args['es_id'] : null;
|
|
|
|
|
|
|
|
|
|
$session = new Db\Session();
|
|
|
|
|
$session->load($esId);
|
|
|
|
|
$session = $this->loadSession($esId);
|
|
|
|
|
|
|
|
|
|
$memberId = isset($args['member_id']) ? $args['member_id'] : null;
|
|
|
|
|
$member = new Db\Member();
|
|
|
|
|
$member->load($memberId);
|
|
|
|
|
|
|
|
|
|
if (!$member->getIsGuest()){
|
|
|
|
|
\OCP\JSON::checkLoggedIn();
|
|
|
|
|
}
|
|
|
|
|
$member = $this->loadMember($memberId);
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
new File($session->getFileId());
|
|
|
|
|
} catch (\Exception $e){
|
|
|
|
|
$this->logger->warning('Error. Session no longer exists. ' . $e->getMessage(), array('app' => $this->appName));
|
|
|
|
|
$ex = new BadRequestException();
|
|
|
|
|
$ex->setBody(
|
|
|
|
|
implode(',', $this->request->getParams())
|
|
|
|
|
);
|
|
|
|
|
throw $ex;
|
|
|
|
|
}
|
|
|
|
|
$this->validateSession($session);
|
|
|
|
|
|
|
|
|
|
switch ($command){
|
|
|
|
|
case 'sync_ops':
|
|
|
|
|
$seqHead = (string) isset($args['seq_head']) ? $args['seq_head'] : null;
|
|
|
|
|
if (!is_null($seqHead)){
|
|
|
|
|
$ops = isset($args['client_ops']) ? $args['client_ops'] : array();
|
|
|
|
|
$ops = isset($args['client_ops']) ? $args['client_ops'] : [];
|
|
|
|
|
|
|
|
|
|
$op = new Db\Op();
|
|
|
|
|
$currentHead = $op->getHeadSeq($esId);
|
|
|
|
@ -177,33 +175,24 @@ class SessionController extends Controller{
|
|
|
|
|
} catch (BadRequestException $e){
|
|
|
|
|
$response->setStatus(Http::STATUS_BAD_REQUEST);
|
|
|
|
|
$response->setData(
|
|
|
|
|
array('err' => 'bad request:[' . $e->getBody() . ']')
|
|
|
|
|
[ 'err' => 'bad request:[' . $e->getBody() . ']' ]
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
return $response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @NoAdminRequired
|
|
|
|
|
* @PublicPage
|
|
|
|
|
* Store the document content to its origin
|
|
|
|
|
* @NoAdminRequired
|
|
|
|
|
*/
|
|
|
|
|
public function save(){
|
|
|
|
|
$response = new JSONResponse();
|
|
|
|
|
try {
|
|
|
|
|
$esId = $this->request->server['HTTP_WEBODF_SESSION_ID'];
|
|
|
|
|
if (!$esId){
|
|
|
|
|
throw new \Exception('Session id can not be empty');
|
|
|
|
|
}
|
|
|
|
|
$session = $this->loadSession($esId);
|
|
|
|
|
|
|
|
|
|
$memberId = $this->request->server['HTTP_WEBODF_MEMBER_ID'];
|
|
|
|
|
$currentMember = new Db\Member();
|
|
|
|
|
$currentMember->load($memberId);
|
|
|
|
|
|
|
|
|
|
//check if member belongs to the session
|
|
|
|
|
if ($esId != $currentMember->getEsId()){
|
|
|
|
|
throw new \Exception($memberId . ' does not belong to session ' . $esId);
|
|
|
|
|
}
|
|
|
|
|
$currentMember = $this->loadMember($memberId, $esId);
|
|
|
|
|
|
|
|
|
|
// Extra info for future usage
|
|
|
|
|
// $sessionRevision = $this->request->server['HTTP_WEBODF_SESSION_REVISION'];
|
|
|
|
@ -215,13 +204,6 @@ class SessionController extends Controller{
|
|
|
|
|
}
|
|
|
|
|
$content = stream_get_contents($stream);
|
|
|
|
|
|
|
|
|
|
$session = new Db\Session();
|
|
|
|
|
$session->load($esId);
|
|
|
|
|
|
|
|
|
|
if (!$session->getEsId()){
|
|
|
|
|
throw new \Exception('Session does not exist');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
if ($currentMember->getIsGuest()){
|
|
|
|
|
$file = File::getByShareToken($currentMember->getToken());
|
|
|
|
@ -229,7 +211,8 @@ class SessionController extends Controller{
|
|
|
|
|
$file = new File($session->getFileId());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
list($view, $path) = $file->getOwnerViewAndPath(true);
|
|
|
|
|
$view = $file->getOwnerView(true);
|
|
|
|
|
$path = $file->getPath(true);
|
|
|
|
|
} catch (\Exception $e){
|
|
|
|
|
//File was deleted or unshared. We need to save content as new file anyway
|
|
|
|
|
//Sorry, but for guests it would be lost :(
|
|
|
|
@ -256,7 +239,7 @@ class SessionController extends Controller{
|
|
|
|
|
$memberCount = count($memberIds) - 1;
|
|
|
|
|
|
|
|
|
|
if ($view->file_exists($path)){
|
|
|
|
|
$currentHash = sha1($view->file_get_contents($path));
|
|
|
|
|
$currentHash = $view->hash('sha1', $path, false);
|
|
|
|
|
|
|
|
|
|
if (!Helper::isVersionsEnabled() && $currentHash !== $session->getGenesisHash()){
|
|
|
|
|
// Original file was modified externally. Save to a new one
|
|
|
|
@ -274,7 +257,7 @@ class SessionController extends Controller{
|
|
|
|
|
// Not a last user
|
|
|
|
|
if ($memberCount>0){
|
|
|
|
|
// Update genesis hash to prevent conflicts
|
|
|
|
|
$this->logger->debug('Update hash', array('app' => $this->appName));
|
|
|
|
|
$this->logger->debug('Update hash', [ 'app' => $this->appName ]);
|
|
|
|
|
$session->updateGenesisHash($esId, sha1($data['content']));
|
|
|
|
|
} else {
|
|
|
|
|
// Last user. Kill session data
|
|
|
|
@ -283,13 +266,56 @@ class SessionController extends Controller{
|
|
|
|
|
|
|
|
|
|
$view->touch($path);
|
|
|
|
|
}
|
|
|
|
|
$response = array('status'=>'success');
|
|
|
|
|
$response->setData(['status'=>'success']);
|
|
|
|
|
} catch (\Exception $e){
|
|
|
|
|
$this->logger->warning('Saving failed. Reason:' . $e->getMessage(), array('app' => $this->appName));
|
|
|
|
|
\OC_Response::setStatus(500);
|
|
|
|
|
$response = array();
|
|
|
|
|
$response->setStatus(Http::STATUS_INTERNAL_SERVER_ERROR);
|
|
|
|
|
$response->setData([]);
|
|
|
|
|
$this->logger->warning('Saving failed. Reason:' . $e->getMessage(), [ 'app' => $this->appName ]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return $response;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function validateSession($session){
|
|
|
|
|
try {
|
|
|
|
|
if (is_null($this->shareToken)) {
|
|
|
|
|
new File($session->getFileId());
|
|
|
|
|
} else {
|
|
|
|
|
File::getByShareToken($this->shareToken);
|
|
|
|
|
}
|
|
|
|
|
} catch (\Exception $e){
|
|
|
|
|
$this->logger->warning('Error. Session no longer exists. ' . $e->getMessage(), [ 'app' => $this->appName ]);
|
|
|
|
|
$ex = new BadRequestException();
|
|
|
|
|
$ex->setBody(
|
|
|
|
|
implode(',', $this->request->getParams())
|
|
|
|
|
);
|
|
|
|
|
throw $ex;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function loadSession($esId){
|
|
|
|
|
if (!$esId){
|
|
|
|
|
throw new \Exception('Session id can not be empty');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$session = new Db\Session();
|
|
|
|
|
$session->load($esId);
|
|
|
|
|
if (!$session->getEsId()){
|
|
|
|
|
throw new \Exception('Session does not exist');
|
|
|
|
|
}
|
|
|
|
|
return $session;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function loadMember($memberId, $expectedEsId = null){
|
|
|
|
|
if (!$memberId){
|
|
|
|
|
throw new \Exception('Member id can not be empty');
|
|
|
|
|
}
|
|
|
|
|
$member = new Db\Member();
|
|
|
|
|
$member->load($memberId);
|
|
|
|
|
//check if member belongs to the session
|
|
|
|
|
if (!is_null($expectedEsId) && $expectedEsId !== $member->getEsId()){
|
|
|
|
|
throw new \Exception($memberId . ' does not belong to session ' . $expectedEsId);
|
|
|
|
|
}
|
|
|
|
|
return $member;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|