Failed Conditions
Pull Request — master (#6)
by Sander
01:54
created

lib/Service/OwnNoteService.php (5 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Nextcloud - passman
4
 *
5
 * @copyright Copyright (c) 2016, Sander Brand ([email protected])
6
 * @copyright Copyright (c) 2016, Marcos Zuriaga Miguel ([email protected])
7
 * @license GNU AGPL version 3 or any later version
8
 *
9
 * This program is free software: you can redistribute it and/or modify
10
 * it under the terms of the GNU Affero General Public License as
11
 * published by the Free Software Foundation, either version 3 of the
12
 * License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU Affero General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU Affero General Public License
20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *
22
 */
23
24
namespace OCA\OwnNote\Service;
25
26
use OCA\OwnNote\Db\OwnNote;
27
use OCA\OwnNote\Utility\Evernote;
28
use OCA\OwnNote\Utility\Utils;
29
use DateTime;
30
use OC\Files\Filesystem;
31
use OCA\OwnNote\Db\OwnNoteMapper;
32
use Punic\Exception;
33
34
35
class OwnNoteService {
36
37
	private $noteMapper;
38
	private $utils;
39
40
	public function __construct(OwnNoteMapper $noteMapper, Utils $utils) {
41
		$this->noteMapper = $noteMapper;
42
		$this->utils = $utils;
43
	}
44
45
	/**
46
	 * Get vaults from a user.
47
	 *
48
	 * @param $userId
49
	 * @return OwnNote[]
50
	 */
51
	public function findNotesFromUser($userId) {
52
		// Get shares
53
		return $this->noteMapper->findNotesFromUser($userId);
54
	}
55
56
	/**
57
	 * Get a single vault
58
	 *
59
	 * @param $note_id
60
	 * @param $user_id
61
	 * @return OwnNote
62
	 * @internal param $vault_id
63
	 */
64
	public function find($note_id, $user_id = null) {
65
		$note = $this->noteMapper->find($note_id, $user_id);
66
		return $note;
67
	}
68
69
	/**
70
	 * Creates a note
71
	 *
72
	 * @param array|OwnNote $note
73
	 * @param $userId
74
	 * @return OwnNote
75
	 * @throws \Exception
76
	 */
77
	public function create($FOLDER, $note, $userId) {
78
		if (is_array($note)) {
79
			$entity = new OwnNote();
80
			$entity->setName($note['name']);
81
			$entity->setUid($userId);
82
			$entity->setGrouping($note['group']);
83
			$entity->setNote($note['note'] ? $note['note'] : '');
84
			if ($note['mtime']) {
85
				$entity->setMtime($note['mtime']);
86
			} else {
87
				$entity->setMtime(time());
88
			}
89
			$note = $entity;
90
		}
91
		if (!$note instanceof OwnNote) {
92
			throw new \Exception("Expected OwnNote object!");
93
		}
94
95
		$group = $note->getGrouping();
96
		$name = $note->getName();
97
		$content = $note->getNote();
98
99 View Code Duplication
		if ($FOLDER != '' && $name) {
100
			$tmpfile = $FOLDER . "/" . $name . ".htm";
101
			if ($group != '')
102
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
103
			Filesystem::file_put_contents($tmpfile, $content);
104
			if ($info = Filesystem::getFileInfo($tmpfile)) {
105
				$mtime = $info['mtime'];
0 ignored issues
show
$mtime is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
106
			}
107
		}
108
109
		return $this->noteMapper->create($note);
110
	}
111
112
	/**
113
	 * Update vault
114
	 *
115
	 * @param $FOLDER
116
	 * @param $note
117
	 * @return OwnNote|bool
118
	 * @throws \Exception
119
	 * @internal param $userId
120
	 * @internal param $vault
121
	 */
122
	public function update($FOLDER, $note) {
123
124
		if (is_array($note)) {
125
			$entity = $this->find($note['id']);
126
			if(!$entity){
127
				$entity = new OwnNote();
128
			}
129
			if (isset($note['name'])) {
130
				$entity->setName($note['name']);
131
			}
132
			if(isset($note['group']) || $note['group']) {
133
				$entity->setGrouping($note['group']);
134
			}
135
136
			if (isset($note['note']) || $note['note'] == '') {
137
				$entity->setNote($note['note']);
138
			}
139
			if (isset($note['mtime'])) {
140
				$entity->setMtime($note['mtime']);
141
			}
142
			$note = $entity;
143
		}
144
		if (!$note instanceof OwnNote) {
145
			throw new \Exception("Expected OwnNote object!");
146
		}
147
		$group = $note->getGrouping();
148
		$name = $note->getName();
149
		$content = $note->getNote();
150
//		if (!$this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE, $note->getId())) {
151
//			return false;
152
//		}
153 View Code Duplication
		if ($FOLDER != '' && $name) {
154
			$tmpfile = $FOLDER . "/" . $name . ".htm";
155
			if ($group != '')
156
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
157
			Filesystem::file_put_contents($tmpfile, $content);
158
			if ($info = Filesystem::getFileInfo($tmpfile)) {
159
				$note->setMtime($info['mtime']);
160
			}
161
		}
162
		if(!$note->getId()){
163
			return $this->noteMapper->create($note);
164
		}
165
		return $this->noteMapper->updateNote($note);
166
	}
167
168
	public function renameNote($FOLDER, $id, $in_newname, $in_newgroup, $uid = null) {
169
		$newname = str_replace("\\", "-", str_replace("/", "-", $in_newname));
170
		$newgroup = str_replace("\\", "-", str_replace("/", "-", $in_newgroup));
171
172
		// We actually need to delete and create so that the delete flag exists for syncing clients
173
		$note = $this->find($id);
174
		$arr = $note->jsonSerialize();
175
		if($note->getName() != $newname || $note->getGrouping() != $newgroup) {
176
			$arr['name'] = $newname;
177
			$arr['group'] = $newgroup;
178
			$this->delete($FOLDER, $note->getId());
179
		}
180
		$this->update($FOLDER, $arr);
181
182
		return true;
183
	}
184
185
	/**
186
	 * Delete a vault from user
187
	 *
188
	 * @param $note_id
189
	 * @param string $user_id
190
	 * @return bool
191
	 * @internal param string $vault_guid
192
	 */
193
	public function delete($FOLDER, $note_id, $user_id = null) {
194
		if (!$this->checkPermissions(\OCP\Constants::PERMISSION_DELETE, $note_id)) {
195
			return false;
196
		}
197
198
		$note = $this->noteMapper->find($note_id, $user_id);
199
		if ($note instanceof OwnNote) {
200
			$group = $note->getGrouping();
201
			$name = $note->getName();
202 View Code Duplication
			if ($FOLDER != '') {
203
				$tmpfile = $FOLDER . "/" . $name . ".htm";
204
				if ($group != '')
205
					$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
206
				if (Filesystem::file_exists($tmpfile))
207
					Filesystem::unlink($tmpfile);
208
			}
209
			$this->noteMapper->deleteNote($note);
210
			return true;
211
		} else {
212
			return false;
213
		}
214
	}
215
216
	/**
217
	 * @param $FOLDER
218
	 * @param OwnNote $note
219
	 */
220
	public function removeFile($FOLDER, $note){
221
		$group = $note->getGrouping();
222
		$name = $note->getName();
223 View Code Duplication
		if ($FOLDER != '') {
224
			$tmpfile = $FOLDER . "/" . $name . ".htm";
225
			if ($group != '')
226
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
227
			if (Filesystem::file_exists($tmpfile))
228
				Filesystem::unlink($tmpfile);
229
		}
230
	}
231
232
	/**
233
	 * @param $FOLDER
234
	 * @param boolean $showdel
235
	 * @return array
236
	 */
237
	public function getListing($FOLDER, $showdel) {
238
		// Get the listing from the database
239
		$requery = false;
240
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
241
		$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
242
		/**
243
		 * @var $results OwnNote[]
244
		 */
245
		$results = array_merge($this->findNotesFromUser($uid), $shared_items);
246
247
		$results2 = $results;
248
		if ($results)
249
			foreach ($results as $result) {
250
				if($result instanceof OwnNote) {
251
					$result = $result->jsonSerialize();
252
				}
253
254
				foreach ($results2 as $result2) {
255
					if($result2 instanceof OwnNote) {
256
						$result2 = $result2->jsonSerialize();
257
					}
258 View Code Duplication
					if ($result['id'] != $result2['id'] && $result['name'] == $result2['name'] && $result['grouping'] == $result2['grouping']) {
259
						// We have a duplicate that should not exist. Need to remove the offending record first
260
						$delid = -1;
261
						if ($result['mtime'] == $result2['mtime']) {
262
							// If the mtime's match, delete the oldest ID.
263
							$delid = $result['id'];
264
							if ($result['id'] > $result2['id'])
265
								$delid = $result2['id'];
266
						} elseif ($result['mtime'] > $result2['mtime']) {
267
							// Again, delete the oldest
268
							$delid = $result2['id'];
269
						} elseif ($result['mtime'] < $result2['mtime']) {
270
							// The only thing left is if result is older
271
							$delid = $result['id'];
272
						}
273
						if ($delid != -1) {
274
							$this->delete('', $delid);
275
							$requery = true;
276
						}
277
					}
278
				}
279
			}
280 View Code Duplication
		if ($requery) {
281
			$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
282
			$results = array_merge($this->findNotesFromUser($uid), $shared_items);
283
			$requery = false;
284
		}
285
286
		// Tests to add a bunch of notes
287
		//$now = new DateTime();
288
		//for ($x = 0; $x < 199; $x++) {
289
		//saveNote('', "Test ".$x, '', '', $now->getTimestamp());
290
		//}
291
		$farray = array();
292
		if ($FOLDER != '') {
293
			// Create the folder if it doesn't exist
294 View Code Duplication
			if (!Filesystem::is_dir($FOLDER)) {
295
				if (!Filesystem::mkdir($FOLDER)) {
296
					\OCP\Util::writeLog('ownnote', 'Could not create ownNote directory.', \OCP\Util::ERROR);
297
					exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method getListing() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
298
				}
299
			}
300
			// Synchronize files to the database
301
			$filearr = array();
302
			if ($listing = Filesystem::opendir($FOLDER)) {
303
				if (!$listing) {
304
					\OCP\Util::writeLog('ownnote', 'Error listing directory.', \OCP\Util::ERROR);
305
					exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method getListing() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
306
				}
307
				while (($file = readdir($listing)) !== false) {
308
					$tmpfile = $file;
309
					if ($tmpfile == "." || $tmpfile == "..") continue;
310
					if (!$this->utils->endsWith($tmpfile, ".htm") && !$this->utils->endsWith($tmpfile, ".html")) continue;
311
					if ($info = Filesystem::getFileInfo($FOLDER . "/" . $tmpfile)) {
312
						// Check for EVERNOTE but wait to rename them to get around:
313
						// https://github.com/owncloud/core/issues/16202
314
						if ($this->utils->endsWith($tmpfile, ".html")) {
315
							Evernote::checkEvernote($FOLDER, $tmpfile);
316
						}
317
						// Separate the name and group name
318
						$name = preg_replace('/\\.[^.\\s]{3,4}$/', '', $tmpfile);
319
						$group = "";
320 View Code Duplication
						if (substr($name, 0, 1) == "[") {
321
							$end = strpos($name, ']');
322
							$group = substr($name, 1, $end - 1);
323
							$name = substr($name, $end + 1, strlen($name) - $end + 1);
324
							$name = trim($name);
325
						}
326
						// Set array for later checking
327
						$filearr[] = $tmpfile;
328
						// Check to see if the file is in the DB
329
						$fileindb = false;
330
						if ($results)
331
							foreach ($results as $result) {
332
								if($result instanceof OwnNote) {
333
									$result = $result->jsonSerialize();
334
								}
335
								if ($result['deleted'] == 0)
336
									if ($name == $result['name'] && $group == $result['grouping']) {
337
										$fileindb = true;
338
										// If it is in the DB, check if the filesystem file is newer than the DB
339
										if ($result['mtime'] < $info['mtime']) {
340
											// File is newer, this could happen if a user updates a file
341
											$html = "";
0 ignored issues
show
$html is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
342
											$html = Filesystem::file_get_contents($FOLDER . "/" . $tmpfile);
343
											$n = [
344
												'id' => $result['id'],
345
												'mtime' => $info['mtime'],
346
												'note' => ($html) ? $html : ''
347
											];
348
											$this->update('', $n);
349
											$requery = true;
350
										}
351
									}
352
							}
353
						if (!$fileindb) {
354
							// If it's not in the DB, add it.
355
							$html = "";
0 ignored issues
show
$html is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
356
							if ($html = Filesystem::file_get_contents($FOLDER . "/" . $tmpfile)) {
357
							} else {
358
								$html = "";
359
							}
360
							$n = [
361
								'name' => $name,
362
								'group' => $group,
363
								'note' => $html,
364
								'mtime' => $info['mtime'],
365
								'uid' => $uid
366
							];
367
							$this->create('', $n, $uid);
368
							$requery = true;
369
						}
370
						// We moved the rename down here to overcome the OC issue
371 View Code Duplication
						if ($this->utils->endsWith($tmpfile, ".html")) {
372
							$tmpfile = substr($tmpfile, 0, -1);
373
							if (!Filesystem::file_exists($FOLDER . "/" . $tmpfile)) {
374
								Filesystem::rename($FOLDER . "/" . $file, $FOLDER . "/" . $tmpfile);
375
							}
376
						}
377
					}
378
				}
379
			}
380 View Code Duplication
			if ($requery) {
381
				$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
382
				$results = array_merge($this->findNotesFromUser($uid), $shared_items);
383
			}
384
			// Now also make sure the files exist, they may not if the user switched folders in admin.
385
			if ($results)
386
				foreach ($results as $result) {
387
					if($result instanceof OwnNote) {
388
						$result = $result->jsonSerialize();
389
					}
390
					if ($result['deleted'] == 0) {
391
						$tmpfile = $result['name'] . ".htm";
392 View Code Duplication
						if ($result['grouping'] != '')
393
							$tmpfile = '[' . $result['grouping'] . '] ' . $result['name'] . '.htm';
394
						$filefound = false;
395
						foreach ($filearr as $f) {
396
							if ($f == $tmpfile) {
397
								$filefound = true;
398
								break;
399
							}
400
						}
401
						if (!$filefound) {
402
							$this->update($FOLDER, $result);
403
						}
404
					}
405
				}
406
		}
407
		// Now loop through and return the listing
408
		if ($results) {
409
			$count = 0;
410
			$now = new \DateTime();
411
			$filetime = new \DateTime();
412
413
			foreach ($results as $result) {
414
				if($result instanceof OwnNote) {
415
					$result = $result->jsonSerialize();
416
				}
417
				if ($result['deleted'] == 0 || $showdel == true) {
418
					$filetime->setTimestamp($result['mtime']);
419
					$timestring = $this->utils->getTimeString($filetime, $now);
420
					$f = array();
421
					$f['id'] = $result['id'];
422
					$f['uid'] = $result['uid'];
423
					$f['name'] = $result['name'];
424
					$f['group'] = ($result['grouping']) ? $result['grouping'] : '';
425
					$f['timestring'] = $timestring;
426
					$f['mtime'] = $result['mtime'];
427
					$f['timediff'] = $now->getTimestamp() - $result['mtime'];
428
					$f['deleted'] = $result['deleted'];
429
					$f['permissions'] = @$result['permissions'];
430
431
432
					$shared_with = \OCP\Share::getUsersItemShared('ownnote', $result['id'], $result['uid']);
433
					// add shares (all shares, if it's an owned note, only the user for shared notes (not disclosing other sharees))
434
					$f['shared_with'] = ($result['uid'] == $uid) ? $shared_with : [$uid];
435
436
					$farray[$count] = $f;
437
					$count++;
438
				}
439
			}
440
		}
441
		return $farray;
442
	}
443
444 View Code Duplication
	private function checkPermissions($permission, $nid) {
445
		// gather information
446
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
447
		$note = $this->find($nid);
448
		// owner is allowed to change everything
449
		if ($uid === $note->getUid()) {
450
			return true;
451
		}
452
453
		// check share permissions
454
		$shared_note = \OCP\Share::getItemSharedWith('ownnote', $nid, 'populated_shares')[0];
455
		return $shared_note['permissions'] & $permission;
456
	}
457
}
458