Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
| 1 | <?php |
||
| 56 | class ShareController extends Controller { |
||
| 57 | |||
| 58 | /** @var \OC\User\Session */ |
||
| 59 | protected $userSession; |
||
| 60 | /** @var \OC\AppConfig */ |
||
| 61 | protected $appConfig; |
||
| 62 | /** @var \OCP\IConfig */ |
||
| 63 | protected $config; |
||
| 64 | /** @var \OC\URLGenerator */ |
||
| 65 | protected $urlGenerator; |
||
| 66 | /** @var \OC\User\Manager */ |
||
| 67 | protected $userManager; |
||
| 68 | /** @var \OCP\ILogger */ |
||
| 69 | protected $logger; |
||
| 70 | /** @var OCP\Activity\IManager */ |
||
| 71 | protected $activityManager; |
||
| 72 | |||
| 73 | /** |
||
| 74 | * @param string $appName |
||
| 75 | * @param IRequest $request |
||
| 76 | * @param OC\User\Session $userSession |
||
| 77 | * @param AppConfig $appConfig |
||
| 78 | * @param OCP\IConfig $config |
||
| 79 | * @param URLGenerator $urlGenerator |
||
| 80 | * @param OCP\IUserManager $userManager |
||
| 81 | * @param ILogger $logger |
||
| 82 | * @param OCP\Activity\IManager $activityManager |
||
| 83 | */ |
||
| 84 | 7 | public function __construct($appName, |
|
| 103 | |||
| 104 | /** |
||
| 105 | * @PublicPage |
||
| 106 | * @NoCSRFRequired |
||
| 107 | * |
||
| 108 | * @param string $token |
||
| 109 | * @return TemplateResponse|RedirectResponse |
||
| 110 | */ |
||
| 111 | 1 | public function showAuthenticate($token) { |
|
| 120 | |||
| 121 | /** |
||
| 122 | * @PublicPage |
||
| 123 | * @UseSession |
||
| 124 | * |
||
| 125 | * Authenticates against password-protected shares |
||
| 126 | * @param $token |
||
| 127 | * @param string $password |
||
| 128 | * @return RedirectResponse|TemplateResponse |
||
| 129 | */ |
||
| 130 | 1 | public function authenticate($token, $password = '') { |
|
| 144 | |||
| 145 | /** |
||
| 146 | * @PublicPage |
||
| 147 | * @NoCSRFRequired |
||
| 148 | * |
||
| 149 | * @param string $token |
||
| 150 | * @param string $path |
||
| 151 | * @return TemplateResponse|RedirectResponse |
||
| 152 | * @throws NotFoundException |
||
| 153 | */ |
||
| 154 | 3 | public function showShare($token, $path = '') { |
|
| 229 | |||
| 230 | /** |
||
| 231 | * @PublicPage |
||
| 232 | * @NoCSRFRequired |
||
| 233 | * |
||
| 234 | * @param string $token |
||
| 235 | * @param string $files |
||
| 236 | * @param string $path |
||
| 237 | * @param string $downloadStartSecret |
||
| 238 | * @return void|RedirectResponse |
||
| 239 | */ |
||
| 240 | 2 | public function downloadShare($token, $files = null, $path = '', $downloadStartSecret = '') { |
|
| 241 | 2 | \OC_User::setIncognitoMode(true); |
|
| 242 | |||
| 243 | 2 | $linkItem = OCP\Share::getShareByToken($token, false); |
|
| 244 | |||
| 245 | // Share is password protected - check whether the user is permitted to access the share |
||
| 246 | 2 | View Code Duplication | if (isset($linkItem['share_with'])) { |
| 247 | 2 | if(!Helper::authenticate($linkItem)) { |
|
| 248 | 1 | return new RedirectResponse($this->urlGenerator->linkToRoute('files_sharing.sharecontroller.authenticate', |
|
| 249 | 1 | array('token' => $token))); |
|
| 250 | } |
||
| 251 | 1 | } |
|
| 252 | |||
| 253 | 1 | $files_list = null; |
|
| 254 | 1 | if (!is_null($files)) { // download selected files |
|
| 255 | $files_list = json_decode($files); |
||
| 256 | // in case we get only a single file |
||
| 257 | if ($files_list === null) { |
||
| 258 | $files_list = array($files); |
||
| 259 | } |
||
| 260 | } |
||
| 261 | |||
| 262 | 1 | $originalSharePath = self::getPath($token); |
|
| 263 | |||
| 264 | // Create the activities |
||
| 265 | if (isset($originalSharePath) && Filesystem::isReadable($originalSharePath . $path)) { |
||
| 266 | $originalSharePath = Filesystem::normalizePath($originalSharePath . $path); |
||
| 267 | $isDir = \OC\Files\Filesystem::is_dir($originalSharePath); |
||
| 268 | |||
| 269 | $activities = []; |
||
| 270 | if (!$isDir) { |
||
| 271 | // Single file public share |
||
| 272 | $activities[$originalSharePath] = Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED; |
||
| 273 | } else if (!empty($files_list)) { |
||
| 274 | // Only some files are downloaded |
||
| 275 | foreach ($files_list as $file) { |
||
| 276 | $filePath = Filesystem::normalizePath($originalSharePath . '/' . $file); |
||
| 277 | $isDir = \OC\Files\Filesystem::is_dir($filePath); |
||
| 278 | $activities[$filePath] = ($isDir) ? Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED : Activity::SUBJECT_PUBLIC_SHARED_FILE_DOWNLOADED; |
||
| 279 | } |
||
| 280 | } else { |
||
| 281 | // The folder is downloaded |
||
| 282 | $activities[$originalSharePath] = Activity::SUBJECT_PUBLIC_SHARED_FOLDER_DOWNLOADED; |
||
| 283 | } |
||
| 284 | |||
| 285 | foreach ($activities as $filePath => $subject) { |
||
| 286 | $this->activityManager->publishActivity( |
||
| 287 | 'files_sharing', $subject, array($filePath), '', array(), |
||
| 288 | $filePath, '', $linkItem['uid_owner'], Activity::TYPE_PUBLIC_LINKS, Activity::PRIORITY_MEDIUM |
||
| 289 | ); |
||
| 290 | } |
||
| 291 | } |
||
| 292 | |||
| 293 | /** |
||
| 294 | * this sets a cookie to be able to recognize the start of the download |
||
| 295 | * the content must not be longer than 32 characters and must only contain |
||
| 296 | * alphanumeric characters |
||
| 297 | */ |
||
| 298 | if (!empty($downloadStartSecret) |
||
| 299 | && !isset($downloadStartSecret[32]) |
||
| 300 | && preg_match('!^[a-zA-Z0-9]+$!', $downloadStartSecret) === 1) { |
||
| 301 | |||
| 302 | // FIXME: set on the response once we use an actual app framework response |
||
| 303 | setcookie('ocDownloadStarted', $downloadStartSecret, time() + 20, '/'); |
||
| 304 | } |
||
| 305 | |||
| 306 | // download selected files |
||
| 307 | if (!is_null($files) && $files !== '') { |
||
| 308 | // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well |
||
| 309 | // after dispatching the request which results in a "Cannot modify header information" notice. |
||
| 310 | OC_Files::get($originalSharePath, $files_list, $_SERVER['REQUEST_METHOD'] == 'HEAD'); |
||
| 311 | exit(); |
||
| 312 | } else { |
||
| 313 | // FIXME: The exit is required here because otherwise the AppFramework is trying to add headers as well |
||
| 314 | // after dispatching the request which results in a "Cannot modify header information" notice. |
||
| 315 | OC_Files::get(dirname($originalSharePath), basename($originalSharePath), $_SERVER['REQUEST_METHOD'] == 'HEAD'); |
||
| 316 | exit(); |
||
| 317 | } |
||
| 318 | } |
||
| 319 | |||
| 320 | /** |
||
| 321 | * @param string $token |
||
| 322 | * @return string Resolved file path of the token |
||
| 323 | * @throws NotFoundException In case share could not get properly resolved |
||
| 324 | */ |
||
| 325 | 4 | private function getPath($token) { |
|
| 346 | } |
||
| 347 |
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.
Either this assignment is in error or an instanceof check should be added for that assignment.