Failed Conditions
Pull Request — master (#8)
by
unknown
01:47
created

lib/backend.php (1 issue)

Severity

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
namespace OCA\OwnNote\Lib;
4
5
\OCP\User::checkLoggedIn();
6
7
use DateTime;
8
use DOMDocument;
9
use OC\Files\Filesystem;
10
use OCA\Admin_Audit\Actions\UserManagement;
11
use OCP\IConfig;
12
use OCP\IL10N;
13
14
class Backend {
15
16
	private $userManager;
17
	private $db;
18
	private $config;
19
20
	/**
21
	 * Backend constructor.
22
	 *
23
	 * @param $userManager \OC\User\Manager
24
	 * @param IConfig $config
25
	 */
26
	public function __construct($userManager, IConfig $config) {
27
		$this->userManager = $userManager;
28
		$this->db = \OC::$server->getDatabaseConnection();
29
		$this->config = $config;
30
	}
31
32
	/**
33
	 * @param $haystack
34
	 * @param $needle
35
	 * @return bool
36
	 */
37
	public function startsWith($haystack, $needle) {
38
		return $needle === "" || strripos($haystack, $needle, -strlen($haystack)) !== false;
39
	}
40
41
	/**
42
	 * @param $string
43
	 * @param $test
44
	 * @return bool
45
	 */
46
	public function endsWith($string, $test) {
47
		$strlen = strlen($string);
48
		$testlen = strlen($test);
49
		if ($testlen > $strlen) return false;
50
		return substr_compare($string, $test, $strlen - $testlen, $testlen, true) === 0;
51
	}
52
53
	/**
54
	 * @param $folder
55
	 * @param $file
56
	 */
57
	public function checkEvernote($folder, $file) {
58
		$html = "";
59
		if ($html = Filesystem::file_get_contents($folder . "/" . $file)) {
60
			$DOM = new DOMDocument;
61
			$DOM->loadHTML($html);
62
			$items = $DOM->getElementsByTagName('meta');
63
			$isEvernote = false;
64
			for ($i = 0; $i < $items->length; $i++) {
65
				$item = $items->item($i);
66
				if ($item->hasAttributes()) {
67
					$attrs = $item->attributes;
68
					foreach ($attrs as $a => $attr) {
69
						if ($attr->name == "name") {
70
							if ($attr->value == "exporter-version" || $attr->value == "Generator") {
71
								$isEvernote = true;
72
								continue;
73
							}
74
						}
75
					}
76
				}
77
			}
78
			if ($isEvernote) {
79
				$items = $DOM->getElementsByTagName('img');
80
				$isEvernote = false;
81
				for ($i = 0; $i < $items->length; $i++) {
82
					$item = $items->item($i);
83
					if ($item->hasAttributes()) {
84
						$attrs = $item->attributes;
85
						foreach ($attrs as $a => $attr) {
86
							if ($attr->name == "src") {
87
								$url = $attr->value;
88
								if (!$this->startsWith($url, "http") && !$this->startsWith($url, "/") && !$this->startsWith($url, "data")) {
89
									if ($data = Filesystem::file_get_contents($folder . "/" . $url)) {
90
										$type = pathinfo($url, PATHINFO_EXTENSION);
91
										$base64 = "data:image/" . $type . ";base64," . base64_encode($data);
92
										$html = str_replace($url, $base64, $html);
93
									}
94
								}
95
							}
96
						}
97
					}
98
				}
99
				Filesystem::file_put_contents($folder . "/" . $file, $html);
100
			}
101
		}
102
	}
103
104
	/**
105
	 * @param $filetime DateTime
106
	 * @param $now DateTime
107
	 * @param $l IL10N
108
	 * @return mixed|string
109
	 */
110
	public function getTimeString($filetime, $now, $l) {
111
		$difftime = $filetime->diff($now);
112
		$years = $difftime->y;
113
		$months = $difftime->m;
114
		$days = $difftime->d;
115
		$hours = $difftime->h;
116
		$minutes = $difftime->i;
117
		$seconds = $difftime->s;
118
		$timestring = "";
119 View Code Duplication
		if ($timestring == "" && $years == 1) $timestring = str_replace('#', $years, $l->t("# year ago"));
120 View Code Duplication
		if ($timestring == "" && $years > 0) $timestring = str_replace('#', $years, $l->t("# years ago"));
121 View Code Duplication
		if ($timestring == "" && $months == 1) $timestring = str_replace('#', $months, $l->t("# month ago"));
122 View Code Duplication
		if ($timestring == "" && $months > 0) $timestring = str_replace('#', $months, $l->t("# months ago"));
123 View Code Duplication
		if ($timestring == "" && $days == 1) $timestring = str_replace('#', $days, $l->t("# day ago"));
124 View Code Duplication
		if ($timestring == "" && $days > 0) $timestring = str_replace('#', $days, $l->t("# days ago"));
125 View Code Duplication
		if ($timestring == "" && $hours == 1) $timestring = str_replace('#', $hours, $l->t("# hour ago"));
126 View Code Duplication
		if ($timestring == "" && $hours > 0) $timestring = str_replace('#', $hours, $l->t("# hours ago"));
127 View Code Duplication
		if ($timestring == "" && $minutes == 1) $timestring = str_replace('#', $minutes, $l->t("# minute ago"));
128 View Code Duplication
		if ($timestring == "" && $minutes > 0) $timestring = str_replace('#', $minutes, $l->t("# minutes ago"));
129 View Code Duplication
		if ($timestring == "" && $seconds == 1) $timestring = str_replace('#', $seconds, $l->t("# second ago"));
130 View Code Duplication
		if ($timestring == "" && $seconds > 0) $timestring = str_replace('#', $seconds, $l->t("# seconds ago"));
131
		return $timestring;
132
	}
133
134
	/**
135
	 * @param $str
136
	 * @return array
137
	 */
138
	public function splitContent($str) {
139
		$maxlength = 2621440; // 5 Megs (2 bytes per character)
140
		$count = 0;
141
		$strarray = array();
142
		while (true) {
143
			if (strlen($str) <= $maxlength) {
144
				$strarray[$count++] = $str;
145
				return $strarray;
146
			} else {
147
				$strarray[$count++] = substr($str, 0, $maxlength);
148
				$str = substr($str, $maxlength);
149
			}
150
		}
151
		return $strarray;
152
	}
153
154
	/**
155
	 * Returns a user's owned and shared notes
156
	 *
157
	 * @param string $uid the user's id
158
	 * @return array the owned notes (uid=uid) and shared notes (OwnnoteShareBackend)
159
	 */
160
	private function queryNotesWithUser($uid) {
161
		// Get owned notes
162
163
		$query = $this->db->executeQuery("SELECT id, uid, name, grouping, mtime, deleted FROM *PREFIX*ownnote WHERE uid=? ORDER BY name", Array($uid));
164
		$results = $query->fetchAll();
165
		// Get shares
166
		$shared_items = \OCP\Share::getItemsSharedWith('ownnote', 'populated_shares');
167
168
		return array_merge($results, $shared_items);
169
	}
170
171
	/**
172
	 * @param $FOLDER
173
	 * @param $showdel
174
	 * @return array
175
	 */
176
	public function getListing($FOLDER, $showdel) {
177
		// Get the listing from the database
178
		$requery = false;
179
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
180
		$results = $this->queryNotesWithUser($uid);
181
182
		$results2 = $results;
183
		if ($results)
184
			foreach ($results as $result) {
185
				foreach ($results2 as $result2) {
186
					if ($result['id'] != $result2['id'] && $result['name'] == $result2['name'] && $result['grouping'] == $result2['grouping']) {
187
						// We have a duplicate that should not exist. Need to remove the offending record first
188
						$delid = -1;
189
						if ($result['mtime'] == $result2['mtime']) {
190
							// If the mtime's match, delete the oldest ID.
191
							$delid = $result['id'];
192
							if ($result['id'] > $result2['id'])
193
								$delid = $result2['id'];
194
						} elseif ($result['mtime'] > $result2['mtime']) {
195
							// Again, delete the oldest
196
							$delid = $result2['id'];
197
						} elseif ($result['mtime'] < $result2['mtime']) {
198
							// The only thing left is if result is older
199
							$delid = $result['id'];
200
						}
201
						if ($delid != -1) {
202
							$this->db->executeQuery("DELETE FROM *PREFIX*ownnote WHERE id=?", Array($delid));
203
							$requery = true;
204
						}
205
					}
206
				}
207
			}
208
		if ($requery) {
209
			$results = $this->queryNotesWithUser($uid);
210
			$requery = false;
211
		}
212
		// Tests to add a bunch of notes
213
		//$now = new DateTime();
214
		//for ($x = 0; $x < 199; $x++) {
215
		//saveNote('', "Test ".$x, '', '', $now->getTimestamp());
216
		//}
217
		$farray = array();
218
		if ($FOLDER != '') {
219
			// Create the folder if it doesn't exist
220
			if (!Filesystem::is_dir($FOLDER)) {
221
				if (!Filesystem::mkdir($FOLDER)) {
222
					\OCP\Util::writeLog('ownnote', 'Could not create ownNote directory.', \OCP\Util::ERROR);
223
					exit;
224
				}
225
			}
226
			// Synchronize files to the database
227
			$filearr = array();
228
			if ($listing = Filesystem::opendir($FOLDER)) {
229
				if (!$listing) {
230
					\OCP\Util::writeLog('ownnote', 'Error listing directory.', \OCP\Util::ERROR);
231
					exit;
232
				}
233
				while (($file = readdir($listing)) !== false) {
234
					$tmpfile = $file;
235
					if ($tmpfile == "." || $tmpfile == "..") continue;
236
					if (!$this->endsWith($tmpfile, ".htm") && !$this->endsWith($tmpfile, ".html")) continue;
237
					if ($info = Filesystem::getFileInfo($FOLDER . "/" . $tmpfile)) {
238
						// Check for EVERNOTE but wait to rename them to get around:
239
						// https://github.com/owncloud/core/issues/16202
240
						if ($this->endsWith($tmpfile, ".html")) {
241
							$this->checkEvernote($FOLDER, $tmpfile);
242
						}
243
						// Separate the name and group name
244
						$name = preg_replace('/\\.[^.\\s]{3,4}$/', '', $tmpfile);
245
						$group = "";
246
						if (substr($name, 0, 1) == "[") {
247
							$end = strpos($name, ']');
248
							$group = substr($name, 1, $end - 1);
249
							$name = substr($name, $end + 1, strlen($name) - $end + 1);
250
							$name = trim($name);
251
						}
252
						// Set array for later checking
253
						$filearr[] = $tmpfile;
254
						// Check to see if the file is in the DB
255
						$fileindb = false;
256
						if ($results)
257
							foreach ($results as $result) {
258
								if ($result['deleted'] == 0)
259
									if ($name == $result['name'] && $group == $result['grouping']) {
260
										$fileindb = true;
261
										// If it is in the DB, check if the filesystem file is newer than the DB
262
										if ($result['mtime'] < $info['mtime']) {
263
											// File is newer, this could happen if a user updates a file
264
											$html = "";
265
											$html = Filesystem::file_get_contents($FOLDER . "/" . $tmpfile);
266
											$this->saveNote('', $result['id'], $html, $info['mtime']);
267
											$requery = true;
268
										}
269
									}
270
							}
271
						if (!$fileindb) {
272
							// If it's not in the DB, add it.
273
							$html = "";
274
							if ($html = Filesystem::file_get_contents($FOLDER . "/" . $tmpfile)) {
275
							} else {
276
								$html = "";
277
							}
278
							$nid = $this->createNote('', $name, $group);
279
							$this->saveNote('', $nid, $html, $info['mtime']);
280
							$requery = true;
281
						}
282
						// We moved the rename down here to overcome the OC issue
283
						if ($this->endsWith($tmpfile, ".html")) {
284
							$tmpfile = substr($tmpfile, 0, -1);
285
							if (!Filesystem::file_exists($FOLDER . "/" . $tmpfile)) {
286
								Filesystem::rename($FOLDER . "/" . $file, $FOLDER . "/" . $tmpfile);
287
							}
288
						}
289
					}
290
				}
291
			}
292
			if ($requery) {
293
				$results = $this->queryNotesWithUser($uid);
294
			}
295
			// Now also make sure the files exist, they may not if the user switched folders in admin.
296
			if ($results)
297
				foreach ($results as $result) {
298
					if ($result['deleted'] == 0) {
299
						$tmpfile = $result['name'] . ".htm";
300
						if ($result['grouping'] != '')
301
							$tmpfile = '[' . $result['grouping'] . '] ' . $result['name'] . '.htm';
302
						$filefound = false;
303
						foreach ($filearr as $f) {
304
							if ($f == $tmpfile) {
305
								$filefound = true;
306
								break;
307
							}
308
						}
309
						if (!$filefound) {
310
							$content = $this->editNote($result['id']);
311
							$this->saveNote($FOLDER,$result['id'], $content, 0);
312
						}
313
					}
314
				}
315
		}
316
		// Now loop through and return the listing
317
		if ($results) {
318
			$count = 0;
319
			$now = new DateTime();
320
			$filetime = new DateTime();
321
			$l = \OCP\Util::getL10N('ownnote');
322
			foreach ($results as $result) {
323
				if ($result['deleted'] == 0 || $showdel == true) {
324
					$filetime->setTimestamp($result['mtime']);
325
					$timestring = $this->getTimeString($filetime, $now, $l);
326
					$f = array();
327
					$f['id'] = $result['id'];
328
					$f['uid'] = $result['uid'];
329
					$f['name'] = $result['name'];
330
					$f['group'] = $result['grouping'];
331
					$f['timestring'] = $timestring;
332
					$f['mtime'] = $result['mtime'];
333
					$f['timediff'] = $now->getTimestamp() - $result['mtime'];
334
					$f['deleted'] = $result['deleted'];
335
336
337
					$shared_with = \OCP\Share::getUsersItemShared('ownnote', $result['id'], $result['uid']);
338
					// add shares (all shares, if it's an owned note, only the user for shared notes (not disclosing other sharees))
339
					$f['shared_with'] = ($result['uid'] == $uid) ? $shared_with : [$uid];
340
341
					$farray[$count] = $f;
342
					$count++;
343
				}
344
			}
345
		}
346
		return $farray;
347
	}
348
349
	/**
350
	 * @param $FOLDER
351
	 * @param $in_name
352
	 * @param $in_group
353
	 * @return int
354
	 */
355
	public function createNote($FOLDER, $in_name, $in_group) {
356
		$name = str_replace("\\", "-", str_replace("/", "-", $in_name));
357
		$group = str_replace("\\", "-", str_replace("/", "-", $in_group));
358
		$now = new DateTime();
359
		$mtime = $now->getTimestamp();
360
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
361
		$fileindb = false;
362
		$filedeldb = false;
363
		$ret = -1;
364
		$query = $this->db->executeQuery("SELECT id, uid, name, grouping, mtime, deleted FROM *PREFIX*ownnote WHERE name=? and grouping=? and uid=?", Array($name, $group, $uid));
365
		$results = $query->fetchAll();
366
		foreach ($results as $result) {
367
			if ($result['deleted'] == 0) {
368
				$fileindb = true;
369
				$ret = $result['id'];
370
			} else {
371
				$filedeldb = true;
372
			}
373
		}
374
		if ($filedeldb) {
375
			$this->db->executeQuery("DELETE FROM *PREFIX*ownnote WHERE name=? and grouping=? and uid=?", Array($name, $group, $uid));
376
		}
377
		// new note
378
		if (!$fileindb) {
379 View Code Duplication
			if ($FOLDER != '') {
380
				$tmpfile = $FOLDER . "/" . $name . ".htm";
381
				if ($group != '')
382
					$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
383
				if (!Filesystem::file_exists($tmpfile)) {
384
					Filesystem::touch($tmpfile);
385
				}
386
				if ($info = Filesystem::getFileInfo($tmpfile)) {
387
					$mtime = $info['mtime'];
388
				}
389
			}
390
			$this->db->executeQuery("INSERT INTO *PREFIX*ownnote (uid, name, grouping, mtime, note, shared) VALUES (?,?,?,?,?,?)", Array($uid, $name, $group, $mtime, '', ''));
391
			$ret = $this->db->lastInsertId('*PREFIX*ownnote');
392
		}
393
		return $ret;
394
	}
395
396
	/**
397
	 * @param $FOLDER
398
	 * @param $nid
399
	 * @return bool
400
	 */
401
	public function deleteNote($FOLDER, $nid) {
402
		if (!$this->checkPermissions(\OCP\Constants::PERMISSION_DELETE, $nid)) {
403
			return false;
404
		}
405
406
		$now = new DateTime();
407
		$mtime = $now->getTimestamp();
408
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
0 ignored issues
show
$uid 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...
409
		$note = $this->getNote($nid);
410
		$name = $note['name'];
411
		$group = $note['group'];
412
		$this->db->executeQuery("UPDATE *PREFIX*ownnote set note='', deleted=1, mtime=? WHERE id=?", Array($mtime, $nid));
413
		//$results = $query->fetchAll();
414
415
		$this->db->executeQuery("DELETE FROM *PREFIX*ownnote_parts WHERE id=?", Array($nid));
416
417
		if ($FOLDER != '') {
418
			$tmpfile = $FOLDER . "/" . $name . ".htm";
419
			if ($group != '')
420
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
421
			if (Filesystem::file_exists($tmpfile))
422
				Filesystem::unlink($tmpfile);
423
		}
424
		return true;
425
	}
426
427
	/**
428
	 * @param $id
429
	 * @return string
430
	 */
431
	public function editNote($id) {
432
		$retVal = "";
433
		$note = $this->getNote($id);
434
435
		// query parts
436
		$query = $this->db->executeQuery("SELECT note FROM *PREFIX*ownnote_parts WHERE id=? order by pid", Array($note['id']));
437
		$results = $query->fetchAll();
438
		foreach ($results as $result) {
439
			$retVal .= $result['note'];
440
		}
441
442
		return $retVal;
443
	}
444
445
	/**
446
	 * @param $FOLDER
447
	 * @param $nid
448
	 * @param $content
449
	 * @param $in_mtime
450
	 * @return bool
451
	 */
452
	public function saveNote($FOLDER, $nid, $content, $in_mtime) {
453
		$maxlength = 2621440; // 5 Megs (2 bytes per character)
454
		$now = new DateTime();
455
		$mtime = $now->getTimestamp();
456
		if ($in_mtime != 0) {
457
			$mtime = $in_mtime;
458
		}
459
460
		// get the specific note
461
		$note = $this->getNote($nid);
462
		$name = $note['name'];
463
		$group = $note['grouping'];
464
465 View Code Duplication
		if ($FOLDER != '') {
466
			$tmpfile = $FOLDER . "/" . $name . ".htm";
467
			if ($group != '')
468
				$tmpfile = $FOLDER . "/[" . $group . "] " . $name . ".htm";
469
			Filesystem::file_put_contents($tmpfile, $content);
470
			if ($info = Filesystem::getFileInfo($tmpfile)) {
471
				$mtime = $info['mtime'];
472
			}
473
		}
474
		$this->db->executeQuery("UPDATE *PREFIX*ownnote set note='', mtime=? WHERE id=?", Array($mtime, $note['id']));
475
476
		$this->db->executeQuery("DELETE FROM *PREFIX*ownnote_parts WHERE id=?", Array($note['id']));
477
		$contentarr = $this->splitContent($content);
478
		for ($i = 0; $i < count($contentarr); $i++) {
479
			$this->db->executeQuery("INSERT INTO *PREFIX*ownnote_parts (id, note) values (?,?)", Array($note['id'], $contentarr[$i]));
480
		}
481
		return true;
482
	}
483
484
	/**
485
	 * @param $FOLDER
486
	 * @param $id
487
	 * @param $in_newname
488
	 * @param $in_newgroup
489
	 * @return bool
490
	 */
491
	public function renameNote($FOLDER, $id, $in_newname, $in_newgroup) {
492
		$newname = str_replace("\\", "-", str_replace("/", "-", $in_newname));
493
		$newgroup = str_replace("\\", "-", str_replace("/", "-", $in_newgroup));
494
495
		// We actually need to delete and create so that the delete flag exists for syncing clients
496
		$content = $this->editNote($id);
497
		$this->deleteNote($FOLDER, $id);
498
499
		$newId = $this->createNote($FOLDER, $newname, $newgroup);
500
		$this->saveNote($FOLDER, $newId, $content, 0);
501
502
		return true;
503
	}
504
505
	/**
506
	 * @param $FOLDER
507
	 * @param $group
508
	 * @return bool
509
	 */
510 View Code Duplication
	public function deleteGroup($FOLDER, $group) {
511
		// We actually need to just rename all the notes
512
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
513
		$query = $this->db->executeQuery("SELECT id, name, grouping, mtime FROM *PREFIX*ownnote WHERE deleted=0 and uid=? and grouping=?", Array($uid, $group));
514
		$results = $query->fetchAll();
515
		foreach ($results as $result) {
516
			$this->renameNote($FOLDER, $result['id'], $result['name'], '');
517
		}
518
		return true;
519
	}
520
521
	/**
522
	 * @param $FOLDER
523
	 * @param $group
524
	 * @param $newgroup
525
	 * @return bool
526
	 */
527 View Code Duplication
	public function renameGroup($FOLDER, $group, $newgroup) {
528
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
529
		$query = $this->db->executeQuery("SELECT id, name, grouping, mtime FROM *PREFIX*ownnote WHERE deleted=0 and uid=? and grouping=?", Array($uid, $group));
530
		$results = $query->fetchAll();
531
		foreach ($results as $result) {
532
			$this->renameNote($FOLDER, $result['id'], $result['name'], $newgroup);
533
		}
534
		return true;
535
	}
536
537
	/**
538
	 * @return string
539
	 */
540
	public function getVersion() {
541
		$v = file_get_contents(__DIR__ . "/../appinfo/version");
542
		if ($v)
543
			return trim($v);
544
		else
545
			return "";
546
	}
547
548
	/**
549
	 * @param $option
550
	 * @param $value
551
	 */
552
	public function setAdminVal($option, $value) {
553
		$this->config->setAppValue('ownnote', $option, $value);
554
		return true;
555
	}
556
557
	/**
558
	 * @param $noteid
559
	 * @return mixed
560
	 */
561
	private function getNote($noteid) {
562
		$query = $this->db->executeQuery("SELECT id, uid, name, grouping, mtime, note, deleted FROM *PREFIX*ownnote WHERE id=?", Array($noteid));
563
		$result = array_shift($query->fetchAll());
564
		return $result;
565
	}
566
567
	/**
568
	 * @param $permission
569
	 * @param $nid
570
	 * @return bool|int
571
	 */
572
	private function checkPermissions($permission, $nid) {
573
		// gather information
574
		$uid = \OC::$server->getUserSession()->getUser()->getUID();
575
		$note = $this->getNote($nid);
576
		// owner is allowed to change everything
577
		if ($uid === $note['uid']) {
578
			return true;
579
		}
580
581
		// check share permissions
582
		$shared_note = \OCP\Share::getItemSharedWith('ownnote', $nid, 'populated_shares')[0];
583
		return $shared_note['permissions'] & $permission;
584
	}
585
}
586
587
?>
588