Failed Conditions
Pull Request — master (#6)
by Sander
01:53
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 OCP\IConfig;
30
use OCP\AppFramework\Db\DoesNotExistException;
31
use DateTime;
32
use DOMDocument;
33
use OC\Files\Filesystem;
34
use OCA\OwnNote\Db\OwnNoteMapper;
35
use Punic\Exception;
36
37
38
class OwnNoteService {
39
40
	private $noteMapper;
41
	private $utils;
42
43
	public function __construct(OwnNoteMapper $noteMapper, Utils $utils) {
44
		$this->noteMapper = $noteMapper;
45
		$this->utils = $utils;
46
	}
47
48
	/**
49
	 * Get vaults from a user.
50
	 *
51
	 * @param $userId
52
	 * @return OwnNote[]
53
	 */
54
	public function findNotesFromUser($userId) {
55
		// Get shares
56
		return $this->noteMapper->findNotesFromUser($userId);
57
	}
58
59
	/**
60
	 * Get a single vault
61
	 *
62
	 * @param $note_id
63
	 * @param $user_id
64
	 * @return OwnNote
65
	 * @internal param $vault_id
66
	 */
67
	public function find($note_id, $user_id = null) {
68
		$note = $this->noteMapper->find($note_id, $user_id);
69
		return $note;
70
	}
71
72
	/**
73
	 * Creates a note
74
	 *
75
	 * @param array|OwnNote $note
76
	 * @param $userId
77
	 * @return OwnNote
78
	 * @throws \Exception
79
	 */
80
	public function create($FOLDER, $note, $userId) {
81
		if (is_array($note)) {
82
			$entity = new OwnNote();
83
			$entity->setName($note['name']);
84
			$entity->setUid($userId);
85
			$entity->setGrouping($note['group']);
86
			$entity->setNote($note['note'] ? $note['note'] : '');
87
			if ($note['mtime']) {
88
				$entity->setMtime($note['mtime']);
89
			} else {
90
				$entity->setMtime(time());
91
			}
92
			$note = $entity;
93
		}
94
		if (!$note instanceof OwnNote) {
95
			throw new \Exception("Expected OwnNote object!");
96
		}
97
98
		$group = $note->getGrouping();
99
		$name = $note->getName();
100
		$content = $note->getNote();
101
102 View Code Duplication
		if ($FOLDER != '' && $name) {
103
			$tmpfile = $FOLDER . "/" . $name . ".htm";
104
			if ($group != '')
105
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
106
			Filesystem::file_put_contents($tmpfile, $content);
107
			if ($info = Filesystem::getFileInfo($tmpfile)) {
108
				$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...
109
			}
110
		}
111
112
		return $this->noteMapper->create($note);
113
	}
114
115
	/**
116
	 * Update vault
117
	 *
118
	 * @param $FOLDER
119
	 * @param $note
120
	 * @return OwnNote|bool
121
	 * @throws \Exception
122
	 * @internal param $userId
123
	 * @internal param $vault
124
	 */
125
	public function update($FOLDER, $note) {
126
127
		if (is_array($note)) {
128
			$entity = $this->find($note['id']);
129
			if(!$entity){
130
				$entity = new OwnNote();
131
			}
132
			if (isset($note['name'])) {
133
				$entity->setName($note['name']);
134
			}
135
			if(isset($note['group']) || $note['group']) {
136
				$entity->setGrouping($note['group']);
137
			}
138
139
			if (isset($note['note']) || $note['note'] == '') {
140
				$entity->setNote($note['note']);
141
			}
142
			if (isset($note['mtime'])) {
143
				$entity->setMtime($note['mtime']);
144
			}
145
			$note = $entity;
146
		}
147
		if (!$note instanceof OwnNote) {
148
			throw new \Exception("Expected OwnNote object!");
149
		}
150
		$group = $note->getGrouping();
151
		$name = $note->getName();
152
		$content = $note->getNote();
153
//		if (!$this->checkPermissions(\OCP\Constants::PERMISSION_UPDATE, $note->getId())) {
154
//			return false;
155
//		}
156 View Code Duplication
		if ($FOLDER != '' && $name) {
157
			$tmpfile = $FOLDER . "/" . $name . ".htm";
158
			if ($group != '')
159
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
160
			Filesystem::file_put_contents($tmpfile, $content);
161
			if ($info = Filesystem::getFileInfo($tmpfile)) {
162
				$note->setMtime($info['mtime']);
163
			}
164
		}
165
		if(!$note->getId()){
166
			return $this->noteMapper->create($note);
167
		}
168
		return $this->noteMapper->updateNote($note);
169
	}
170
171
	public function renameNote($FOLDER, $id, $in_newname, $in_newgroup, $uid = null) {
172
		$newname = str_replace("\\", "-", str_replace("/", "-", $in_newname));
173
		$newgroup = str_replace("\\", "-", str_replace("/", "-", $in_newgroup));
174
175
		// We actually need to delete and create so that the delete flag exists for syncing clients
176
		$note = $this->find($id);
177
		$arr = $note->jsonSerialize();
178
		if($note->getName() != $newname || $note->getGrouping() != $newgroup) {
179
			$arr['name'] = $newname;
180
			$arr['group'] = $newgroup;
181
			$this->delete($FOLDER, $note->getId());
182
		}
183
		$this->update($FOLDER, $arr);
184
185
		return true;
186
	}
187
188
	/**
189
	 * Delete a vault from user
190
	 *
191
	 * @param $note_id
192
	 * @param string $user_id
193
	 * @return bool
194
	 * @internal param string $vault_guid
195
	 */
196
	public function delete($FOLDER, $note_id, $user_id = null) {
197
		if (!$this->checkPermissions(\OCP\Constants::PERMISSION_DELETE, $note_id)) {
198
			return false;
199
		}
200
201
		$note = $this->noteMapper->find($note_id, $user_id);
202
		if ($note instanceof OwnNote) {
203
			$group = $note->getGrouping();
204
			$name = $note->getName();
205 View Code Duplication
			if ($FOLDER != '') {
206
				$tmpfile = $FOLDER . "/" . $name . ".htm";
207
				if ($group != '')
208
					$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
209
				if (Filesystem::file_exists($tmpfile))
210
					Filesystem::unlink($tmpfile);
211
			}
212
			$this->noteMapper->deleteNote($note);
213
			return true;
214
		} else {
215
			return false;
216
		}
217
	}
218
219
	/**
220
	 * @param $FOLDER
221
	 * @param OwnNote $note
222
	 */
223
	public function removeFile($FOLDER, $note){
224
		$group = $note->getGrouping();
225
		$name = $note->getName();
226 View Code Duplication
		if ($FOLDER != '') {
227
			$tmpfile = $FOLDER . "/" . $name . ".htm";
228
			if ($group != '')
229
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
230
			if (Filesystem::file_exists($tmpfile))
231
				Filesystem::unlink($tmpfile);
232
		}
233
	}
234
235
	/**
236
	 * @param $FOLDER
237
	 * @param $showdel
238
	 * @return array
239
	 */
240
	public function getListing($FOLDER, $showdel) {
241
		// Get the listing from the database
242
		$requery = false;
243
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
244
		$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
245
		/**
246
		 * @var $results OwnNote[]
247
		 */
248
		$results = array_merge($this->findNotesFromUser($uid), $shared_items);
249
250
		$results2 = $results;
251
		if ($results)
252
			foreach ($results as $result) {
253
				if($result instanceof OwnNote) {
254
					$result = $result->jsonSerialize();
255
				}
256
257
				foreach ($results2 as $result2) {
258
					if($result2 instanceof OwnNote) {
259
						$result2 = $result2->jsonSerialize();
260
					}
261 View Code Duplication
					if ($result['id'] != $result2['id'] && $result['name'] == $result2['name'] && $result['grouping'] == $result2['grouping']) {
262
						// We have a duplicate that should not exist. Need to remove the offending record first
263
						$delid = -1;
264
						if ($result['mtime'] == $result2['mtime']) {
265
							// If the mtime's match, delete the oldest ID.
266
							$delid = $result['id'];
267
							if ($result['id'] > $result2['id'])
268
								$delid = $result2['id'];
269
						} elseif ($result['mtime'] > $result2['mtime']) {
270
							// Again, delete the oldest
271
							$delid = $result2['id'];
272
						} elseif ($result['mtime'] < $result2['mtime']) {
273
							// The only thing left is if result is older
274
							$delid = $result['id'];
275
						}
276
						if ($delid != -1) {
277
							$this->delete('', $delid);
278
							$requery = true;
279
						}
280
					}
281
				}
282
			}
283 View Code Duplication
		if ($requery) {
284
			$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
285
			$results = array_merge($this->findNotesFromUser($uid), $shared_items);
286
			$requery = false;
287
		}
288
289
		// Tests to add a bunch of notes
290
		//$now = new DateTime();
291
		//for ($x = 0; $x < 199; $x++) {
292
		//saveNote('', "Test ".$x, '', '', $now->getTimestamp());
293
		//}
294
		$farray = array();
295
		if ($FOLDER != '') {
296
			// Create the folder if it doesn't exist
297 View Code Duplication
			if (!Filesystem::is_dir($FOLDER)) {
298
				if (!Filesystem::mkdir($FOLDER)) {
299
					\OCP\Util::writeLog('ownnote', 'Could not create ownNote directory.', \OCP\Util::ERROR);
300
					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...
301
				}
302
			}
303
			// Synchronize files to the database
304
			$filearr = array();
305
			if ($listing = Filesystem::opendir($FOLDER)) {
306
				if (!$listing) {
307
					\OCP\Util::writeLog('ownnote', 'Error listing directory.', \OCP\Util::ERROR);
308
					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...
309
				}
310
				while (($file = readdir($listing)) !== false) {
311
					$tmpfile = $file;
312
					if ($tmpfile == "." || $tmpfile == "..") continue;
313
					if (!$this->utils->endsWith($tmpfile, ".htm") && !$this->utils->endsWith($tmpfile, ".html")) continue;
314
					if ($info = Filesystem::getFileInfo($FOLDER . "/" . $tmpfile)) {
315
						// Check for EVERNOTE but wait to rename them to get around:
316
						// https://github.com/owncloud/core/issues/16202
317
						if ($this->utils->endsWith($tmpfile, ".html")) {
318
							Evernote::checkEvernote($FOLDER, $tmpfile);
319
						}
320
						// Separate the name and group name
321
						$name = preg_replace('/\\.[^.\\s]{3,4}$/', '', $tmpfile);
322
						$group = "";
323 View Code Duplication
						if (substr($name, 0, 1) == "[") {
324
							$end = strpos($name, ']');
325
							$group = substr($name, 1, $end - 1);
326
							$name = substr($name, $end + 1, strlen($name) - $end + 1);
327
							$name = trim($name);
328
						}
329
						// Set array for later checking
330
						$filearr[] = $tmpfile;
331
						// Check to see if the file is in the DB
332
						$fileindb = false;
333
						if ($results)
334
							foreach ($results as $result) {
335
								if($result instanceof OwnNote) {
336
									$result = $result->jsonSerialize();
337
								}
338
								if ($result['deleted'] == 0)
339
									if ($name == $result['name'] && $group == $result['grouping']) {
340
										$fileindb = true;
341
										// If it is in the DB, check if the filesystem file is newer than the DB
342
										if ($result['mtime'] < $info['mtime']) {
343
											// File is newer, this could happen if a user updates a file
344
											$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...
345
											$html = Filesystem::file_get_contents($FOLDER . "/" . $tmpfile);
346
											$n = [
347
												'id' => $result['id'],
348
												'mtime' => $info['mtime'],
349
												'note' => ($html) ? $html : ''
350
											];
351
											$this->update('', $n);
352
											$requery = true;
353
										}
354
									}
355
							}
356
						if (!$fileindb) {
357
							// If it's not in the DB, add it.
358
							$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...
359
							if ($html = Filesystem::file_get_contents($FOLDER . "/" . $tmpfile)) {
360
							} else {
361
								$html = "";
362
							}
363
							$n = [
364
								'name' => $name,
365
								'group' => $group,
366
								'note' => $html,
367
								'mtime' => $info['mtime'],
368
								'uid' => $uid
369
							];
370
							$this->create('', $n, $uid);
371
							$requery = true;
372
						}
373
						// We moved the rename down here to overcome the OC issue
374 View Code Duplication
						if ($this->utils->endsWith($tmpfile, ".html")) {
375
							$tmpfile = substr($tmpfile, 0, -1);
376
							if (!Filesystem::file_exists($FOLDER . "/" . $tmpfile)) {
377
								Filesystem::rename($FOLDER . "/" . $file, $FOLDER . "/" . $tmpfile);
378
							}
379
						}
380
					}
381
				}
382
			}
383 View Code Duplication
			if ($requery) {
384
				$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
385
				$results = array_merge($this->findNotesFromUser($uid), $shared_items);
386
			}
387
			// Now also make sure the files exist, they may not if the user switched folders in admin.
388
			if ($results)
389
				foreach ($results as $result) {
390
					if($result instanceof OwnNote) {
391
						$result = $result->jsonSerialize();
392
					}
393
					if ($result['deleted'] == 0) {
394
						$tmpfile = $result['name'] . ".htm";
395 View Code Duplication
						if ($result['grouping'] != '')
396
							$tmpfile = '[' . $result['grouping'] . '] ' . $result['name'] . '.htm';
397
						$filefound = false;
398
						foreach ($filearr as $f) {
399
							if ($f == $tmpfile) {
400
								$filefound = true;
401
								break;
402
							}
403
						}
404
						if (!$filefound) {
405
							$this->update($FOLDER, $result);
406
						}
407
					}
408
				}
409
		}
410
		// Now loop through and return the listing
411
		if ($results) {
412
			$count = 0;
413
			$now = new \DateTime();
414
			$filetime = new \DateTime();
415
416
			foreach ($results as $result) {
417
				if($result instanceof OwnNote) {
418
					$result = $result->jsonSerialize();
419
				}
420
				if ($result['deleted'] == 0 || $showdel == true) {
421
					$filetime->setTimestamp($result['mtime']);
422
					$timestring = $this->utils->getTimeString($filetime, $now);
423
					$f = array();
424
					$f['id'] = $result['id'];
425
					$f['uid'] = $result['uid'];
426
					$f['name'] = $result['name'];
427
					$f['group'] = ($result['grouping']) ? $result['grouping'] : '';
428
					$f['timestring'] = $timestring;
429
					$f['mtime'] = $result['mtime'];
430
					$f['timediff'] = $now->getTimestamp() - $result['mtime'];
431
					$f['deleted'] = $result['deleted'];
432
					$f['permissions'] = @$result['permissions'];
433
434
435
					$shared_with = \OCP\Share::getUsersItemShared('ownnote', $result['id'], $result['uid']);
436
					// add shares (all shares, if it's an owned note, only the user for shared notes (not disclosing other sharees))
437
					$f['shared_with'] = ($result['uid'] == $uid) ? $shared_with : [$uid];
438
439
					$farray[$count] = $f;
440
					$count++;
441
				}
442
			}
443
		}
444
		return $farray;
445
	}
446
447 View Code Duplication
	private function checkPermissions($permission, $nid) {
448
		// gather information
449
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
450
		$note = $this->find($nid);
451
		// owner is allowed to change everything
452
		if ($uid === $note->getUid()) {
453
			return true;
454
		}
455
456
		// check share permissions
457
		$shared_note = \OCP\Share::getItemSharedWith('ownnote', $nid, 'populated_shares')[0];
458
		return $shared_note['permissions'] & $permission;
459
	}
460
}
461