Completed
Push — master ( d35b5f...2bf577 )
by Lukas
05:59 queued 05:51
created

WopiController::parseFileId()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 17
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 17
ccs 0
cts 16
cp 0
rs 9.4285
cc 3
eloc 13
nc 3
nop 1
crap 12
1
<?php
2
/**
3
 * @copyright Copyright (c) 2016 Lukas Reschke <[email protected]>
4
 *
5
 * @license GNU AGPL version 3 or any later version
6
 *
7
 * This program is free software: you can redistribute it and/or modify
8
 * it under the terms of the GNU Affero General Public License as
9
 * published by the Free Software Foundation, either version 3 of the
10
 * License, or (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
namespace OCA\Richdocuments\Controller;
23
24
use OC\Files\View;
25
use OCA\Richdocuments\Db\Wopi;
26
use OCA\Richdocuments\Helper;
27
use OCA\Richdocuments\WOPI\Parser;
28
use OCP\AppFramework\Controller;
29
use OCP\AppFramework\Http;
30
use OCP\AppFramework\Http\JSONResponse;
31
use OCP\Files\File;
32
use OCP\Files\IRootFolder;
33
use OCP\IRequest;
34
use OCP\IUserManager;
35
use OCP\AppFramework\Http\StreamResponse;
36
37
class WopiController extends Controller {
38
	/** @var IRootFolder */
39
	private $rootFolder;
40
41
	/**
42
	 * @param string $appName
43
	 * @param IRequest $request
44
	 * @param IRootFolder $rootFolder
45
	 * @param string $UserId
46
	 */
47
	public function __construct($appName,
48
								$UserId,
49
								IRequest $request,
50
								IRootFolder $rootFolder) {
51
		parent::__construct($appName, $request);
52
		$this->rootFolder = $rootFolder;
53
	}
54
55
	/**
56
	 * Returns general info about a file.
57
	 *
58
	 * @NoAdminRequired
59
	 * @NoCSRFRequired
60
	 * @PublicPage
61
	 *
62
	 * @param string $fileId
63
	 * @return JSONResponse
64
	 */
65
	public function checkFileInfo($fileId) {
66
		$token = $this->request->getParam('access_token');
67
68
		list($fileId, , $version) = Helper::parseFileId($fileId);
69
		$db = new Wopi();
70
		$res = $db->getPathForToken($fileId, $token);
71
		if ($res === false) {
72
			return new JSONResponse([], Http::STATUS_FORBIDDEN);
73
		}
74
75
		// Login the user to see his mount locations
76
		try {
77
			/** @var File $file */
78
			$userFolder = $this->rootFolder->getUserFolder($res['owner']);
79
			$file = $userFolder->getById($fileId)[0];
80
		} catch (\Exception $e) {
81
			return new JSONResponse([], Http::STATUS_FORBIDDEN);
82
		}
83
84
		if(!($file instanceof File)) {
0 ignored issues
show
Bug introduced by
The class OCP\Files\File does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
85
			return new JSONResponse([], Http::STATUS_FORBIDDEN);
86
		}
87
88
		return new JSONResponse(
89
			[
90
				'BaseFileName' => $file->getName(),
91
				'Size' => $file->getSize(),
92
				'Version' => $version,
93
				'UserId' => $res['editor'] !== '' ? $res['editor'] : 'Guest user',
94
				'OwnerId' => $res['owner'],
95
				'UserFriendlyName' => $res['editor'] !== '' ? $res['editor'] : 'Guest user',
96
				'UserCanWrite' => $res['canwrite'] ? true : false,
97
				'PostMessageOrigin' => $res['server_host'],
98
			]
99
		);
100
	}
101
102
	/**
103
	 * Given an access token and a fileId, returns the contents of the file.
104
	 * Expects a valid token in access_token parameter.
105
	 *
106
	 * @PublicPage
107
	 * @NoCSRFRequired
108
	 *
109
	 * @param string $fileId
110
	 * @param string $access_token
111
	 * @return Http\Response
112
	 */
113
	public function getFile($fileId,
114
							$access_token) {
115
		list($fileId, , $version) = Helper::parseFileId($fileId);
116
		$row = new Wopi();
117
		$row->loadBy('token', $access_token);
118
		$res = $row->getPathForToken($fileId, $access_token);
119
		try {
120
			/** @var File $file */
121
			$userFolder = $this->rootFolder->getUserFolder($res['owner']);
122
			$file = $userFolder->getById($fileId)[0];
123
124
			if ($version !== '0')
125
			{
126
				$view = new View('/' . $res['owner'] . '/files');
127
				$relPath = $view->getRelativePath($file->getPath());
128
				$versionPath = '/files_versions/' . $relPath . '.v' . $version;
129
				$view = new View('/' . $res['owner']);
130
				if ($view->file_exists($versionPath)){
131
					$response = new StreamResponse($view->fopen($versionPath, 'rb'));
132
				}
133
				else {
134
					$response->setStatus(Http::STATUS_NOT_FOUND);
0 ignored issues
show
Bug introduced by
The variable $response seems only to be defined at a later point. Did you maybe move this code here without moving the variable definition?

This error can happen if you refactor code and forget to move the variable initialization.

Let’s take a look at a simple example:

function someFunction() {
    $x = 5;
    echo $x;
}

The above code is perfectly fine. Now imagine that we re-order the statements:

function someFunction() {
    echo $x;
    $x = 5;
}

In that case, $x would be read before it is initialized. This was a very basic example, however the principle is the same for the found issue.

Loading history...
135
				}
136
			}
137
			else
138
			{
139
				$response = new StreamResponse($file->fopen('rb'));
140
			}
141
			$response->addHeader('Content-Disposition', 'attachment');
0 ignored issues
show
Bug introduced by
The variable $response does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
142
			$response->addHeader('Content-Type', 'application/octet-stream');
143
			return $response;
144
		} catch (\Exception $e) {
145
			return new JSONResponse([], Http::STATUS_FORBIDDEN);
146
		}
147
	}
148
149
	/**
150
	 * Given an access token and a fileId, replaces the files with the request body.
151
	 * Expects a valid token in access_token parameter.
152
	 *
153
	 * @PublicPage
154
	 * @NoCSRFRequired
155
	 *
156
	 * @param string $fileId
157
	 * @param string $access_token
158
	 * @return JSONResponse
159
	 */
160
	public function putFile($fileId,
161
							$access_token) {
162
		list($fileId, , $version) = Helper::parseFileId($fileId);
0 ignored issues
show
Unused Code introduced by
The assignment to $version is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
163
164
		$row = new Wopi();
165
		$row->loadBy('token', $access_token);
166
167
		$res = $row->getPathForToken($fileId, $access_token);
168
		if (!$res['canwrite']) {
169
			return new JSONResponse([], Http::STATUS_FORBIDDEN);
170
		}
171
172
		try {
173
			/** @var File $file */
174
			$userFolder = $this->rootFolder->getUserFolder($res['owner']);
175
			$file = $userFolder->getById($fileId)[0];
176
			$content = fopen('php://input', 'rb');
177
			// Setup the FS which is needed to emit hooks (versioning).
178
			\OC_Util::tearDownFS();
179
			\OC_Util::setupFS($res['owner']);
180
			$file->putContent($content);
181
			return new JSONResponse();
182
		} catch (\Exception $e) {
183
			return new JSONResponse([], Http::STATUS_INTERNAL_SERVER_ERROR);
184
		}
185
	}
186
}
187