1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
<?php
/**
* ownCloud - Richdocuments App
*
* @author Ashod Nakashian
* @copyright 2016 Ashod Nakashian ashod.nakashian@collabora.co.uk
*
* This file is licensed under the Affero General Public License version 3 or
* later.
*/
namespace OCA\Richdocuments\Db;
use \OCA\Richdocuments\Download;
use \OCA\Richdocuments\DownloadResponse;
/**
* @method string generateFileToken()
* @method string getPathForToken()
*/
class Wopi extends \OCA\Richdocuments\Db{
const DB_TABLE = '`*PREFIX*richdocuments_wopi`';
// Tokens expire after this many seconds (not defined by WOPI specs).
const TOKEN_LIFETIME_SECONDS = 1800;
protected $tableName = '`*PREFIX*richdocuments_wopi`';
protected $insertStatement = 'INSERT INTO `*PREFIX*richdocuments_wopi` (`uid`, `fileid`, `path`, `token`, `expiry`)
VALUES (?, ?, ?, ?, ?)';
protected $loadStatement = 'SELECT * FROM `*PREFIX*richdocuments_wopi` WHERE `token`= ?';
/*
* Given a fileId, generates a token
* and stores in the database.
* Returns the token.
*/
public function generateFileToken($fileId){
// Get the FS view of the current user.
$view = \OC\Files\Filesystem::getView();
// Get the virtual path (if the file is shared).
$path = $view->getPath($fileId);
if (!$view->is_file($path) || !$view->isUpdatable($path)) {
throw new \Exception('Invalid fileId.');
}
// Figure out the real owner, if not us.
$user = $view->getOwner($path);
// Create a view into the owner's FS.
$view = new \OC\Files\View('/' . $user . '/files');
// Find the real path.
$path = $view->getPath($fileId);
if (!$view->is_file($path)) {
throw new \Exception('Invalid fileId.');
}
$token = \OC::$server->getSecureRandom()->getMediumStrengthGenerator()->generate(32,
\OCP\Security\ISecureRandom::CHAR_LOWER . \OCP\Security\ISecureRandom::CHAR_UPPER .
\OCP\Security\ISecureRandom::CHAR_DIGITS);
\OC::$server->getLogger()->debug('Issuing token for {user} file {fileId}, path {path}: {token}',
[ 'user' => $user, 'fileId' => $fileId, 'path' => $path, 'token' => $token ]);
$wopi = new \OCA\Richdocuments\Db\Wopi([
$user,
$fileId,
$path,
$token,
time() + self::TOKEN_LIFETIME_SECONDS
]);
if (!$wopi->insert()){
throw new \Exception('Failed to add wopi token into database');
}
return $token;
}
/*
* Given a token, validates it and
* constructs and validates the path.
* Returns the path, if valid, else false.
*/
public function getPathForToken($fileId, $token){
$wopi = new Wopi();
$row = $wopi->loadBy('token', $token)->getData();
\OC::$server->getLogger()->debug('Loaded WOPI Token record: {row}.', [ 'row' => $row ]);
if (count($row) == 0)
{
// Invalid token.
http_response_code(401);
return false;
}
//TODO: validate.
if ($row['expiry'] > time()){
// Expired token!
//http_response_code(404);
//$wopi->deleteBy('id', $row['id']);
//return false;
}
if ($row['fileid'] !== $fileId){
// File unknown / user unauthorized (for the requested file).
http_response_code(404);
return false;
}
$user = $row['uid'];
$view = new \OC\Files\View('/' . $user . '/files');
$path = $row['path'];
if (!$view->is_file($path)) {
throw new \Exception('Invalid file path.');
}
return array('user' => $user, 'path' => $path);
}
}
|