X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/37bf7f11e4361902ad92ceaf6bd15f1f85b76188..refs/pull/1462/head:/app/Entities/Repos/EntityRepo.php diff --git a/app/Entities/Repos/EntityRepo.php b/app/Entities/Repos/EntityRepo.php index 6fc2689a5..a0934530f 100644 --- a/app/Entities/Repos/EntityRepo.php +++ b/app/Entities/Repos/EntityRepo.php @@ -1,5 +1,6 @@ books()->sync($syncData); } + /** + * Append a Book to a BookShelf. + * @param Bookshelf $shelf + * @param Book $book + */ + public function appendBookToShelf(Bookshelf $shelf, Book $book) + { + if ($shelf->contains($book)) { + return; + } + + $maxOrder = $shelf->books()->max('order'); + $shelf->books()->attach($book->id, ['order' => $maxOrder + 1]); + } + /** * Change the book that an entity belongs to. * @param string $type * @param integer $newBookId * @param Entity $entity * @param bool $rebuildPermissions - * @return \BookStack\Entities\Entity + * @return Entity */ public function changeBook($type, $newBookId, Entity $entity, $rebuildPermissions = false) { @@ -700,6 +720,7 @@ class EntityRepo } $doc = new DOMDocument(); + libxml_use_internal_errors(true); $doc->loadHTML(mb_convert_encoding(''.$matchedPage->html.'', 'HTML-ENTITIES', 'UTF-8')); $matchingElem = $doc->getElementById($splitInclude[1]); if ($matchingElem === null) { @@ -715,6 +736,7 @@ class EntityRepo $innerContent .= $doc->saveHTML($childNode); } } + libxml_clear_errors(); $html = str_replace($matches[0][$index], trim($innerContent), $html); } @@ -728,13 +750,35 @@ class EntityRepo */ protected function escapeScripts(string $html) : string { - $scriptSearchRegex = '/.*?<\/script>/ms'; - $matches = []; - preg_match_all($scriptSearchRegex, $html, $matches); + if ($html == '') { + return $html; + } + + libxml_use_internal_errors(true); + $doc = new DOMDocument(); + $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); + $xPath = new DOMXPath($doc); + + // Remove standard script tags + $scriptElems = $xPath->query('//body//*//script'); + foreach ($scriptElems as $scriptElem) { + $scriptElem->parentNode->removeChild($scriptElem); + } - foreach ($matches[0] as $match) { - $html = str_replace($match, htmlentities($match), $html); + // Remove 'on*' attributes + $onAttributes = $xPath->query('//body//*/@*[starts-with(name(), \'on\')]'); + foreach ($onAttributes as $attr) { + /** @var \DOMAttr $attr*/ + $attrName = $attr->nodeName; + $attr->parentNode->removeAttribute($attrName); } + + $html = ''; + $topElems = $doc->documentElement->childNodes->item(0)->childNodes; + foreach ($topElems as $child) { + $html .= $doc->saveHTML($child); + } + return $html; } @@ -745,7 +789,7 @@ class EntityRepo */ public function searchForImage($imageString) { - $pages = $this->entityQuery('page')->where('html', 'like', '%' . $imageString . '%')->get(); + $pages = $this->entityQuery('page')->where('html', 'like', '%' . $imageString . '%')->get(['id', 'name', 'slug', 'book_id']); foreach ($pages as $page) { $page->url = $page->getUrl(); $page->html = ''; @@ -756,8 +800,8 @@ class EntityRepo /** * Destroy a bookshelf instance - * @param \BookStack\Entities\Bookshelf $shelf - * @throws \Throwable + * @param Bookshelf $shelf + * @throws Throwable */ public function destroyBookshelf(Bookshelf $shelf) { @@ -767,9 +811,9 @@ class EntityRepo /** * Destroy the provided book and all its child entities. - * @param \BookStack\Entities\Book $book + * @param Book $book * @throws NotifyException - * @throws \Throwable + * @throws Throwable */ public function destroyBook(Book $book) { @@ -785,8 +829,8 @@ class EntityRepo /** * Destroy a chapter and its relations. - * @param \BookStack\Entities\Chapter $chapter - * @throws \Throwable + * @param Chapter $chapter + * @throws Throwable */ public function destroyChapter(Chapter $chapter) { @@ -804,7 +848,7 @@ class EntityRepo * Destroy a given page along with its dependencies. * @param Page $page * @throws NotifyException - * @throws \Throwable + * @throws Throwable */ public function destroyPage(Page $page) { @@ -827,12 +871,12 @@ class EntityRepo /** * Destroy or handle the common relations connected to an entity. - * @param \BookStack\Entities\Entity $entity - * @throws \Throwable + * @param Entity $entity + * @throws Throwable */ protected function destroyEntityCommonRelations(Entity $entity) { - \Activity::removeEntity($entity); + Activity::removeEntity($entity); $entity->views()->delete(); $entity->permissions()->delete(); $entity->tags()->delete(); @@ -844,9 +888,9 @@ class EntityRepo /** * Copy the permissions of a bookshelf to all child books. * Returns the number of books that had permissions updated. - * @param \BookStack\Entities\Bookshelf $bookshelf + * @param Bookshelf $bookshelf * @return int - * @throws \Throwable + * @throws Throwable */ public function copyBookshelfPermissions(Bookshelf $bookshelf) {