From 73d18f3d9472aa26fb6a02ea5317f1b7a1f9247b Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Fri, 21 Jul 2023 11:44:54 +0200 Subject: [PATCH 01/26] chore: v3.2.0-RC.3 --- CHANGELOG.md | 4 ++-- package.json | 2 +- phpmyfaq/src/phpMyFAQ/System.php | 2 +- scripts/version.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66ae4a352e..9e55f538ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# phpMyFAQ 3.2.0 +# phpMyFAQ 3.2.0-RC.3 **Codename "Pontus"** @@ -6,7 +6,7 @@ This is a log of major user-visible changes in each phpMyFAQ release. -### phpMyFAQ v3.2.0 - 2023-07- +### phpMyFAQ v3.2.0-RC.3 - 2023-07-21 - changed PHP requirement to PHP 8.1.0 or later (Thorsten) - changed to HTTPS as new default (Thorsten) diff --git a/package.json b/package.json index d0a60185b5..9a1d9e574a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thorsten/phpmyfaq", - "version": "3.2.0", + "version": "3.2.0-RC.3", "description": "phpMyFAQ", "repository": "git://github.com/thorsten/phpMyFAQ.git", "author": "Thorsten Rinne", diff --git a/phpmyfaq/src/phpMyFAQ/System.php b/phpmyfaq/src/phpMyFAQ/System.php index eb1955afbd..fbea21eb12 100644 --- a/phpmyfaq/src/phpMyFAQ/System.php +++ b/phpmyfaq/src/phpMyFAQ/System.php @@ -51,7 +51,7 @@ class System /** * Pre-release version. */ - private const VERSION_PRE_RELEASE = ''; + private const VERSION_PRE_RELEASE = 'RC.3'; /** * API version. diff --git a/scripts/version.sh b/scripts/version.sh index 3b84195d96..44b20d2c86 100644 --- a/scripts/version.sh +++ b/scripts/version.sh @@ -1,4 +1,4 @@ #!/bin/sh if [ "x${PMF_VERSION}" = "x" ]; then - PMF_VERSION="3.2.0" + PMF_VERSION="3.2.0-RC.3" fi From 0141611775c636c9b60b26475bb2ce960d21609f Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sat, 22 Jul 2023 15:15:42 +0200 Subject: [PATCH 02/26] fix: corrected breadcrumb output (#2553) --- phpmyfaq/src/phpMyFAQ/Category.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/phpmyfaq/src/phpMyFAQ/Category.php b/phpmyfaq/src/phpMyFAQ/Category.php index 9a375869fb..11ed50878b 100755 --- a/phpmyfaq/src/phpMyFAQ/Category.php +++ b/phpmyfaq/src/phpMyFAQ/Category.php @@ -935,9 +935,9 @@ public function getPath( $categoryId[$key] ); $oLink = new Link($url, $this->config); - $oLink->text = sprintf('%s', Strings::htmlentities($category)); + $oLink->text = Strings::htmlentities($category); $oLink->itemTitle = Strings::htmlentities($category); - $oLink->tooltip = Strings::htmlentities($description[$key]); + $oLink->tooltip = !is_null($description[$key]) ? Strings::htmlentities($description[$key]) : ''; if (0 === $key) { $oLink->setRelation('index'); } From bf4950beeb52655b2589790d885e49f3d7cf0f4b Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sat, 22 Jul 2023 15:28:24 +0200 Subject: [PATCH 03/26] fix: allow styles in tables, closes #2553 --- phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php index c53c4e549a..438a17babd 100644 --- a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php +++ b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php @@ -267,6 +267,18 @@ public function cleanUpContent(string $content): string ], 'span' => [ 'allowed_attributes' => ['class', 'style'], + ], + 'table' => [ + 'allowed_attributes' => ['class', 'style'], + ], + 'tr' => [ + 'allowed_attributes' => ['class', 'style'], + ], + 'th' => [ + 'allowed_attributes' => ['class', 'style'], + ], + 'td' => [ + 'allowed_attributes' => ['class', 'style'], ] ], From 43311c33a838f6fc9574135b8b79c09dff0efbd1 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sun, 23 Jul 2023 17:00:12 +0200 Subject: [PATCH 04/26] fix: added missing sequence table for PostgreSQL --- phpmyfaq/src/phpMyFAQ/Database/DatabaseDriver.php | 7 +++---- phpmyfaq/src/phpMyFAQ/Database/Mysqli.php | 3 +-- phpmyfaq/src/phpMyFAQ/Database/Pgsql.php | 3 +-- phpmyfaq/src/phpMyFAQ/Database/Sqlite3.php | 2 +- phpmyfaq/src/phpMyFAQ/Database/Sqlsrv.php | 3 +-- phpmyfaq/src/phpMyFAQ/Instance/Database/Pgsql.php | 10 ++++++---- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/phpmyfaq/src/phpMyFAQ/Database/DatabaseDriver.php b/phpmyfaq/src/phpMyFAQ/Database/DatabaseDriver.php index 23d569b2b3..827546755e 100644 --- a/phpmyfaq/src/phpMyFAQ/Database/DatabaseDriver.php +++ b/phpmyfaq/src/phpMyFAQ/Database/DatabaseDriver.php @@ -125,12 +125,11 @@ public function getTableStatus(string $prefix = ''): array; /** * Returns the next ID of a table. * - * @param string The name of the table - * @param string the name of the ID column - * + * @param string $table The name of the table + * @param string $id the name of the ID column * @return int */ - public function nextId($table, $id): int; + public function nextId(string $table, string $id): int; /** * Returns the error string. diff --git a/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php b/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php index 8467589313..0ebcad2c1b 100644 --- a/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php +++ b/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php @@ -309,10 +309,9 @@ private function getOne($query): string * * @param string $table The name of the table * @param string $id The name of the ID column - * * @return int */ - public function nextId($table, $id): int + public function nextId(string $table, string $id): int { $select = sprintf( ' diff --git a/phpmyfaq/src/phpMyFAQ/Database/Pgsql.php b/phpmyfaq/src/phpMyFAQ/Database/Pgsql.php index 13ab9e2d2a..01e6e242b1 100644 --- a/phpmyfaq/src/phpMyFAQ/Database/Pgsql.php +++ b/phpmyfaq/src/phpMyFAQ/Database/Pgsql.php @@ -256,10 +256,9 @@ private function getOne($query): string * * @param string $table the name of the table * @param string $id the name of the ID column - * * @return int */ - public function nextId($table, $id): int + public function nextId(string $table, string $id): int { return (int) $this->getOne("SELECT nextval('" . $table . '_' . $id . "_seq') as current_id;"); } diff --git a/phpmyfaq/src/phpMyFAQ/Database/Sqlite3.php b/phpmyfaq/src/phpMyFAQ/Database/Sqlite3.php index 35c737597d..1e0cdc2dad 100644 --- a/phpmyfaq/src/phpMyFAQ/Database/Sqlite3.php +++ b/phpmyfaq/src/phpMyFAQ/Database/Sqlite3.php @@ -328,7 +328,7 @@ public function getTableNames(string $prefix = ''): array * * @return int */ - public function nextId($table, $id): int + public function nextId(string $table, string $id): int { $result = (int)$this->conn->querySingle( sprintf( diff --git a/phpmyfaq/src/phpMyFAQ/Database/Sqlsrv.php b/phpmyfaq/src/phpMyFAQ/Database/Sqlsrv.php index b7632c5368..b8d96633f0 100644 --- a/phpmyfaq/src/phpMyFAQ/Database/Sqlsrv.php +++ b/phpmyfaq/src/phpMyFAQ/Database/Sqlsrv.php @@ -255,10 +255,9 @@ public function query(string $query, int $offset = 0, int $rowcount = 0) * * @param string $table the name of the table * @param string $id the name of the ID column - * * @return int */ - public function nextId($table, $id): int + public function nextId(string $table, string $id): int { $select = sprintf( ' diff --git a/phpmyfaq/src/phpMyFAQ/Instance/Database/Pgsql.php b/phpmyfaq/src/phpMyFAQ/Instance/Database/Pgsql.php index 7b0ffce607..cab96cebbd 100644 --- a/phpmyfaq/src/phpMyFAQ/Instance/Database/Pgsql.php +++ b/phpmyfaq/src/phpMyFAQ/Instance/Database/Pgsql.php @@ -30,9 +30,7 @@ class Pgsql extends Database implements Driver /** * @var array */ - private $createTableStatements = [ - 'faquser_user_id_seq' => 'CREATE SEQUENCE %sfaquser_user_id_seq START WITH 2', - + private array $createTableStatements = [ 'faqadminlog' => 'CREATE TABLE %sfaqadminlog ( id SERIAL NOT NULL, time INTEGER NOT NULL, @@ -43,7 +41,7 @@ class Pgsql extends Database implements Driver 'faqattachment' => 'CREATE TABLE %sfaqattachment ( id SERIAL NOT NULL, - record_id SERIAL NOT NULL, + record_id INTEGER NOT NULL, record_lang VARCHAR(5) NOT NULL, real_hash CHAR(32) NOT NULL, virtual_hash CHAR(32) NOT NULL, @@ -105,6 +103,8 @@ class Pgsql extends Database implements Driver position INTEGER NOT NULL, PRIMARY KEY (category_id))', + 'faqcategory_order_position_seq' => 'CREATE SEQUENCE %sfaqcategory_order_position_seq START WITH 1', + 'faqcategory_user' => 'CREATE TABLE %sfaqcategory_user ( category_id INTEGER NOT NULL, user_id INTEGER NOT NULL, @@ -339,6 +339,8 @@ class Pgsql extends Database implements Driver login_attempts SMALLINT NULL DEFAULT 0, PRIMARY KEY (user_id))', + 'faquser_user_id_seq' => 'CREATE SEQUENCE %sfaquser_user_id_seq START WITH 2', + 'faquserdata' => 'CREATE TABLE %sfaquserdata ( user_id SERIAL NOT NULL, last_modified VARCHAR(14) NULL, From 97d90ebbe11ebc6081bf49a2ba4b60f227cd1b43 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Thu, 27 Jul 2023 08:02:56 +0200 Subject: [PATCH 05/26] fix: added missing conversion to HTML entities --- phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php | 9 +++++++-- phpmyfaq/src/phpMyFAQ/Helper/SearchHelper.php | 6 +++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php index 438a17babd..4863ba4f05 100644 --- a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php +++ b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php @@ -187,11 +187,16 @@ public function createOverview(Category $category, Faq $faq, string $language = $lastCategory = 0; foreach ($faq->faqRecords as $data) { if ($data['category_id'] !== $lastCategory) { - $output .= sprintf('

%s

', $category->getPath($data['category_id'], ' » ')); + $output .= sprintf( + '

%s

', + $this->cleanUpContent( + $this->cleanUpContent($category->getPath($data['category_id'], ' » ')) + ) + ); } $output .= sprintf('

%s

', Strings::htmlentities($data['title'])); - $output .= sprintf('
%s
', $data['content']); + $output .= sprintf('
%s
', $this->cleanUpContent($data['content'])); $output .= sprintf( '

%s: %s
%s', $PMF_LANG['msgAuthor'], diff --git a/phpmyfaq/src/phpMyFAQ/Helper/SearchHelper.php b/phpmyfaq/src/phpMyFAQ/Helper/SearchHelper.php index 0cc69406da..ff2f09397d 100644 --- a/phpmyfaq/src/phpMyFAQ/Helper/SearchHelper.php +++ b/phpmyfaq/src/phpMyFAQ/Helper/SearchHelper.php @@ -258,14 +258,14 @@ public function renderSearchResult(SearchResultSet $resultSet, int $currentPage) ); $oLink = new Link($currentUrl, $this->config); - $oLink->text = $question; - $oLink->itemTitle = $oLink->tooltip = $result->question; + $oLink->text = Strings::htmlentities($question); + $oLink->itemTitle = $oLink->tooltip = Strings::htmlentities($result->question); $html .= '

  • '; $html .= $this->renderScore($result->score * 33); $html .= sprintf( '%s: %s
    ', - $categoryInfo[0]['name'], + Strings::htmlentities($categoryInfo[0]['name']), $oLink->toHtmlAnchor() ); $html .= sprintf( From 52bc469a58f310992cc455d896f61d7657dde39a Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Fri, 28 Jul 2023 12:39:57 +0200 Subject: [PATCH 06/26] fix: added missing import --- phpmyfaq/api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpmyfaq/api.php b/phpmyfaq/api.php index c4017d20df..151d92bea8 100644 --- a/phpmyfaq/api.php +++ b/phpmyfaq/api.php @@ -30,6 +30,7 @@ use phpMyFAQ\Faq\FaqMetaData; use phpMyFAQ\Faq\FaqPermission; use phpMyFAQ\Filter; +use phpMyFAQ\Helper\QuestionHelper; use phpMyFAQ\Helper\RegistrationHelper; use phpMyFAQ\Language; use phpMyFAQ\News; From 84093d7d612ffe0706eee02c66c19e958972f432 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sat, 29 Jul 2023 11:09:19 +0200 Subject: [PATCH 07/26] feat: added API to update FAQs as well --- API.md | 1 + CHANGELOG.md | 6 ++-- api-docs/faq/post.md | 2 +- api-docs/faq/put.md | 80 ++++++++++++++++++++++++++++++++++++++++++++ phpmyfaq/api.php | 27 ++++++++++----- 5 files changed, 103 insertions(+), 13 deletions(-) create mode 100644 api-docs/faq/put.md diff --git a/API.md b/API.md index 796a444d92..d64ba6697a 100644 --- a/API.md +++ b/API.md @@ -52,6 +52,7 @@ be acquired from the admin configuration. ### FAQ related APIs - [Add FAQ](api-docs/faq/post.md): `POST /api/v2.2/faq` +- [Update FAQ](api-docs/faq/put.md): `PUT /api/v2.2/faq/:categoryId/:faqId` - [Add question](api-docs/question/post.md): `POST /api/v2.2/question` ### Groups related APIs diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e55f538ef..5f7ee75818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# phpMyFAQ 3.2.0-RC.3 +# phpMyFAQ 3.2.0 **Codename "Pontus"** @@ -6,7 +6,7 @@ This is a log of major user-visible changes in each phpMyFAQ release. -### phpMyFAQ v3.2.0-RC.3 - 2023-07-21 +### phpMyFAQ v3.2.0 - 2023-08- - changed PHP requirement to PHP 8.1.0 or later (Thorsten) - changed to HTTPS as new default (Thorsten) @@ -19,7 +19,7 @@ This is a log of major user-visible changes in each phpMyFAQ release. - added 2FA (Two-Factor Authentication) (Jan Harms) - added experimental Azure AD login (Thorsten) - added option to use Google ReCaptcha (Thorsten) -- added REST API v2.2 to fetch groups and add categories (Thorsten) +- added REST API v2.2 to fetch groups, add categories, and update FAQs (Thorsten) - added verification of backup files (Thorsten) - added option to disable questions and notifications (Thorsten) - added new options for more flexibility (Jan Harms) diff --git a/api-docs/faq/post.md b/api-docs/faq/post.md index e94fbe9d22..bd3d7f1e13 100644 --- a/api-docs/faq/post.md +++ b/api-docs/faq/post.md @@ -41,7 +41,7 @@ mapped, the category ID from the name will be used. If the category name cannot ```json { "language": "de", - "category-id": "1", + "category-id": 1, "category-name": "Queen Songs", "question": "Is this the world we created?", "answer": "What did we do it for, is this the world we invaded, against the law, so it seems in the end, is this what we're all living for today", diff --git a/api-docs/faq/put.md b/api-docs/faq/put.md new file mode 100644 index 0000000000..3c49882758 --- /dev/null +++ b/api-docs/faq/put.md @@ -0,0 +1,80 @@ +# Update a FAQ + +Used to update a FAQ in one existing category. + +**URL** : `/api/v2.1/faq` + +**HTTP Header** : + +``` +Accept-Language: [language code] +X-PMF-Token: [phpMyFAQ client API Token, generated in admin backend] +Content-Type: application/json +``` + +**Method** : `POST` + +**Auth required** : NO + +**Data constraints** + +```json +{ + "faq-id": "[faq id as integer value, required value]", + "language": "[language code, required value]", + "category-id": "[category id as integer value, required value]", + "question": "[question in plain text, required value]", + "answer": "[question in plain text, required value]", + "keywords": "[keywords in comma separated plain text or empty string, required value]", + "author": "[author name in plain text, required value]", + "email": "[author email in plain text, required value]", + "is-active": "true/false, required value", + "is-sticky": "true/false, required value" +} +``` + +**Data example** + +```json +{ + "faq-id": 1, + "language": "de", + "category-id": 1, + "question": "Is this the world we created?", + "answer": "What did we do it for, is this the world we invaded, against the law, so it seems in the end, is this what we're all living for today", + "keywords": "phpMyFAQ, FAQ, Foo, Bar", + "author": "Freddie Mercury", + "email": "freddie.mercury@example.org", + "is-active": "true", + "is-sticky": "false" +} +``` + +## Success Response + +**Condition** : If all putted data is correct. + +**Code** : `200 OK` + +**Content example** + +```json +{ + "stored": true +} +``` + +## Error Responses + +**Condition** : If FAQ ID or category id cannot be mapped to valid IDs + +**Code** : `404 Not Found` + +**Content** : + +```json +{ + "stored": false, + "error": "error message" +} +``` diff --git a/phpmyfaq/api.php b/phpmyfaq/api.php index 151d92bea8..20b08e21ce 100644 --- a/phpmyfaq/api.php +++ b/phpmyfaq/api.php @@ -421,7 +421,7 @@ $faq->setUser($currentUser); $faq->setGroups($currentGroups); - if ($recordId > 0) { + if ($request->getMethod() === 'GET' && $recordId > 0) { $faq->getRecord($recordId); $result = $faq->faqRecord; @@ -443,7 +443,7 @@ } // - // POST + // POST or PUT // if ($faqConfig->get('api.apiClientToken') !== $request->headers->get('x-pmf-token')) { $response->setStatusCode(Response::HTTP_UNAUTHORIZED); @@ -462,6 +462,11 @@ $postData = json_decode(file_get_contents('php://input'), true, 512, JSON_THROW_ON_ERROR); + if (isset($postData['faq-id'])) { + $faqId = Filter::filterVar($postData['faq-id'], FILTER_VALIDATE_INT); + } else { + $faqId = null; + } $languageCode = Filter::filterVar($postData['language'], FILTER_SANITIZE_SPECIAL_CHARS); $categoryId = Filter::filterVar($postData['category-id'], FILTER_VALIDATE_INT); if (isset($postData['category-name'])) { @@ -510,14 +515,18 @@ ->setComment(false) ->setNotes(''); - $faqId = $faq->create($faqData); + if (is_null($faqId)) { + $faqId = $faq->create($faqData); + } else { + $faqData->setId($faqId); + $faqData->setRevisionId(0); + $faq->update($faqData); + } - $faqMetaData = new FaqMetaData($faqConfig); - $faqMetaData - ->setFaqId($faqId) - ->setFaqLanguage($languageCode) - ->setCategories($categories) - ->save(); + if ($request->getMethod() !== 'PUT') { + $faqMetaData = new FaqMetaData($faqConfig); + $faqMetaData->setFaqId($faqId)->setFaqLanguage($languageCode)->setCategories($categories)->save(); + } $result = [ 'stored' => true From 9f52b75b3ccc67c3e794115af14180ffc98b3c57 Mon Sep 17 00:00:00 2001 From: sasama Date: Tue, 1 Aug 2023 20:38:35 +0900 Subject: [PATCH 08/26] Fix: admin-search-faqs --- phpmyfaq/admin/record.show.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/admin/record.show.php b/phpmyfaq/admin/record.show.php index b4b8e2925e..f14bd5cb50 100644 --- a/phpmyfaq/admin/record.show.php +++ b/phpmyfaq/admin/record.show.php @@ -164,7 +164,7 @@ ] ); - if (is_numeric($searchTerm)) { + if (is_numeric($searchTerm) && $faqConfig->get('search.searchForSolutionId')) { $search->setMatchingColumns([$fdTable . '.solution_id']); } else { $search->setMatchingColumns([$fdTable . '.thema', $fdTable . '.content', $fdTable . '.keywords']); From 99072f9803d8afa4e133216e62b4d48a98418917 Mon Sep 17 00:00:00 2001 From: sasama Date: Tue, 1 Aug 2023 20:54:29 +0900 Subject: [PATCH 09/26] Fix: tagid-type-error --- phpmyfaq/search.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/search.php b/phpmyfaq/search.php index 7837c63269..c2cd2a8547 100755 --- a/phpmyfaq/search.php +++ b/phpmyfaq/search.php @@ -103,7 +103,7 @@ $tagHelper->setTaggingIds($tagIds); foreach ($tagIds as $tagId) { - if (!isset($tags[$tagId])) { + if (!isset($tags[$tagId]) && is_numeric($tagId)) { $tags[$tagId] = $tagging->getTagNameById($tagId); } } From 11aad7e75013aa56d08fb69867afd40f3bdfd1eb Mon Sep 17 00:00:00 2001 From: sasama Date: Tue, 1 Aug 2023 21:28:35 +0900 Subject: [PATCH 10/26] Fix: faqid-type-error --- phpmyfaq/faq.php | 2 +- phpmyfaq/index.php | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/phpmyfaq/faq.php b/phpmyfaq/faq.php index 346c34467a..0e6a51404b 100644 --- a/phpmyfaq/faq.php +++ b/phpmyfaq/faq.php @@ -75,7 +75,7 @@ $currentCategory = $cat; $request = Request::createFromGlobals(); -$faqId = Filter::filterVar($request->query->get('id'), FILTER_VALIDATE_INT); +$faqId = Filter::filterVar($request->query->get('id'), FILTER_VALIDATE_INT, 0); $solutionId = Filter::filterVar($request->query->get('solution_id'), FILTER_VALIDATE_INT); $highlight = Filter::filterVar($request->query->get('highlight'), FILTER_SANITIZE_SPECIAL_CHARS); diff --git a/phpmyfaq/index.php b/phpmyfaq/index.php index fc3ca9077b..8aa793e169 100755 --- a/phpmyfaq/index.php +++ b/phpmyfaq/index.php @@ -332,8 +332,8 @@ // // Found a record ID? // -$id = Filter::filterVar($request->query->get('id'), FILTER_VALIDATE_INT); -if (!is_null($id)) { +$id = Filter::filterVar($request->query->get('id'), FILTER_VALIDATE_INT, 0); +if ($id !== 0) { $faq->getRecord($id); $title = ' - ' . $faq->faqRecord['title']; $keywords = ',' . $faq->faqRecord['keywords']; @@ -350,7 +350,6 @@ $faqLink->itemTitle = $faq->faqRecord['title']; $currentPageUrl = $faqLink->toString(true); } else { - $id = ''; $title = ' - ' . System::getPoweredByString(); $keywords = ''; $metaDescription = str_replace('"', '', (string) $faqConfig->get('main.metaDescription')); From 9289f8504ec21a0252986ec1c2e553cff28bc383 Mon Sep 17 00:00:00 2001 From: sasama Date: Mon, 14 Aug 2023 14:30:57 +0900 Subject: [PATCH 11/26] Fix: rememberme input field --- phpmyfaq/admin/login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/admin/login.php b/phpmyfaq/admin/login.php index 5ce71b8e64..567d573342 100644 --- a/phpmyfaq/admin/login.php +++ b/phpmyfaq/admin/login.php @@ -75,7 +75,7 @@
    - From 255b65ed6b3d40d3094f0225c78e26d51e1ebc16 Mon Sep 17 00:00:00 2001 From: sasama Date: Fri, 18 Aug 2023 14:09:51 +0900 Subject: [PATCH 12/26] Fix: remove nl2br --- phpmyfaq/admin/record.save.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/admin/record.save.php b/phpmyfaq/admin/record.save.php index 6ae30d00f5..eeee149015 100644 --- a/phpmyfaq/admin/record.save.php +++ b/phpmyfaq/admin/record.save.php @@ -137,7 +137,7 @@ // Create ChangeLog entry $changelog = new Changelog($faqConfig); - $changelog->add($recordId, $user->getUserId(), nl2br((string) $changed), $recordLang, $revisionId); + $changelog->add($recordId, $user->getUserId(), (string) $changed, $recordLang, $revisionId); // Create the visit entry $visits = new Visits($faqConfig); From 147bec96baa690a0a06d1dff897b68a4385a3532 Mon Sep 17 00:00:00 2001 From: sasama Date: Fri, 18 Aug 2023 13:45:14 +0900 Subject: [PATCH 13/26] Fix: copyentry tags --- phpmyfaq/admin/record.edit.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpmyfaq/admin/record.edit.php b/phpmyfaq/admin/record.edit.php index 594291a296..a66efdcf1c 100644 --- a/phpmyfaq/admin/record.edit.php +++ b/phpmyfaq/admin/record.edit.php @@ -188,6 +188,7 @@ $faq->getRecord($faqData['id'], null, true); $faqData = $faq->faqRecord; + $faqData['tags'] = implode(', ', $tagging->getAllTagsById($faqData['id'])); $queryString = 'insertentry'; } else { $logging = new AdminLog($faqConfig); From 1d1ca0c822fd50ce109bed5c4c86eb06c8f7cf81 Mon Sep 17 00:00:00 2001 From: sasama Date: Fri, 18 Aug 2023 15:23:38 +0900 Subject: [PATCH 14/26] Fix: system menu entry --- phpmyfaq/admin/header.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/admin/header.php b/phpmyfaq/admin/header.php index dee90c01d4..5c61d08469 100644 --- a/phpmyfaq/admin/header.php +++ b/phpmyfaq/admin/header.php @@ -110,7 +110,7 @@ $secLevelEntries['backup'] = $adminHelper->addMenuEntry('editconfig', 'backup', 'ad_menu_backup', $action); $secLevelEntries['config'] = $adminHelper->addMenuEntry('editconfig', 'config', 'ad_menu_editconfig', $action); -$secLevelEntries['config'] .= $adminHelper->addMenuEntry('editconfig', 'system', 'ad_system_info', $action, false); +$secLevelEntries['config'] .= $adminHelper->addMenuEntry('editconfig', 'system', 'ad_system_info', $action); $secLevelEntries['config'] .= $adminHelper->addMenuEntry( 'editinstances+addinstances+delinstances', 'instances', From fc0ed6a1f5bc4a71884596969fcfe92a50b0e93e Mon Sep 17 00:00:00 2001 From: sasama Date: Sun, 20 Aug 2023 15:00:47 +0900 Subject: [PATCH 15/26] Fix: revision display --- phpmyfaq/admin/record.edit.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/admin/record.edit.php b/phpmyfaq/admin/record.edit.php index a66efdcf1c..099a5c34d0 100644 --- a/phpmyfaq/admin/record.edit.php +++ b/phpmyfaq/admin/record.edit.php @@ -330,7 +330,7 @@
    perm->hasPermission($currentUserId, 'changebtrevs')) { + if ($user->perm->hasPermission($currentUserId, 'changebtrevs') && $action === 'editentry') { $faqRevision = new Revision($faqConfig); $revisions = $faqRevision->get($faqData['id'], $faqData['lang'], $faqData['author']); if (count($revisions)) { ?> From 6ca5e9798b4ac610fe80a16807638aeb8ac19bcc Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Wed, 23 Aug 2023 12:03:04 +0200 Subject: [PATCH 16/26] feat: support for 4 Byte unicode characters, closes #2585 --- phpmyfaq/src/phpMyFAQ/Database/Mysqli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php b/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php index 835eb699a2..cfaafaddc9 100644 --- a/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php +++ b/phpmyfaq/src/phpMyFAQ/Database/Mysqli.php @@ -84,7 +84,7 @@ public function connect( } // change character set to UTF-8 - if (!$this->conn->set_charset('utf8')) { + if (!$this->conn->set_charset('utf8mb4')) { Database::errorPage($this->error()); } From 1037a8f012e0d9ec4bf4c8107972f6695e381392 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Wed, 23 Aug 2023 12:22:08 +0200 Subject: [PATCH 17/26] fix: added missing conversion to HTML entities --- phpmyfaq/admin/ajax.tags.php | 3 ++- phpmyfaq/admin/assets/js/tags.js | 10 +++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/phpmyfaq/admin/ajax.tags.php b/phpmyfaq/admin/ajax.tags.php index b4172ca663..e2023e7ad8 100644 --- a/phpmyfaq/admin/ajax.tags.php +++ b/phpmyfaq/admin/ajax.tags.php @@ -17,6 +17,7 @@ use phpMyFAQ\Filter; use phpMyFAQ\Helper\HttpHelper; +use phpMyFAQ\Strings; use phpMyFAQ\Tags; use phpMyFAQ\Entity\TagEntity as TagEntity; @@ -55,7 +56,7 @@ ++$i; if ($i <= PMF_TAGS_AUTOCOMPLETE_RESULT_SET_SIZE) { $currentTag = new stdClass(); - $currentTag->tagName = $tagName; + $currentTag->tagName = Strings::htmlentities($tagName); $tagNames[] = $currentTag; } } diff --git a/phpmyfaq/admin/assets/js/tags.js b/phpmyfaq/admin/assets/js/tags.js index 87e4f75337..94c84885fc 100644 --- a/phpmyfaq/admin/assets/js/tags.js +++ b/phpmyfaq/admin/assets/js/tags.js @@ -24,7 +24,7 @@ document.addEventListener('DOMContentLoaded', () => { span.replaceWith(''); } else { const input = $('input[data-tag-id="' + id + '"]'); - input.replaceWith('' + input.val().replace(/\//g, '/') + ''); + input.replaceWith('' + escape(input.val().replace(/\//g, '/')) + ''); } }); @@ -36,10 +36,6 @@ document.addEventListener('DOMContentLoaded', () => { const tag = input.val(); const csrf = $('input[name=csrf]').val(); - const escape = (unsafe) => { - return unsafe.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", '''); - } - $.ajax({ url: 'index.php?action=ajax&ajax=tags&ajaxaction=update', type: 'POST', @@ -59,4 +55,8 @@ document.addEventListener('DOMContentLoaded', () => { return false; }); + + const escape = (unsafe) => { + return unsafe.replaceAll('&', '&').replaceAll('<', '<').replaceAll('>', '>').replaceAll('"', '"').replaceAll("'", '''); + } }); From ec1d709fc732a6098066ecd27d7657ba20ffba31 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Wed, 23 Aug 2023 18:17:04 +0200 Subject: [PATCH 18/26] fix: corrected duplicated HTML entities --- phpmyfaq/assets/themes/default/templates/search.html | 6 +++++- phpmyfaq/show.php | 3 ++- phpmyfaq/src/phpMyFAQ/Faq.php | 6 +++--- phpmyfaq/src/phpMyFAQ/Helper/SearchHelper.php | 6 +++--- phpmyfaq/src/phpMyFAQ/Link.php | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/phpmyfaq/assets/themes/default/templates/search.html b/phpmyfaq/assets/themes/default/templates/search.html index adaae7e754..76d34fabed 100644 --- a/phpmyfaq/assets/themes/default/templates/search.html +++ b/phpmyfaq/assets/themes/default/templates/search.html @@ -8,7 +8,11 @@

    {{ msgTags }}

    [/tagListSection] [relatedTags]

    {{ relatedTagsHeader }}

    {{ relatedTags }}
    - [/relatedTags] {{ renderSearchResults }} [searchBoxSection] + [/relatedTags] + + {{ renderSearchResults }} + + [searchBoxSection] From c687eb8f58e31cb8ede2befee9c48b334f175b69 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sat, 26 Aug 2023 11:41:39 +0200 Subject: [PATCH 22/26] fix: allow borders in tables, closes #2560 --- phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php index 8b8d7d3644..6bb95d8bee 100644 --- a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php +++ b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php @@ -275,7 +275,7 @@ public function cleanUpContent(string $content): string 'allowed_attributes' => ['class', 'style'], ], 'table' => [ - 'allowed_attributes' => ['class', 'style'], + 'allowed_attributes' => ['class', 'style', 'border'], ], 'tr' => [ 'allowed_attributes' => ['class', 'style'], From 7c6b1b8d27b23e0f32cadca94b283592617a9e62 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sun, 27 Aug 2023 18:39:09 +0200 Subject: [PATCH 23/26] chore: v3.1.17 --- CHANGELOG.md | 7 ++++++- package.json | 2 +- phpmyfaq/src/phpMyFAQ/System.php | 2 +- scripts/version.sh | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 668cfe56f7..4bbfb60cb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# phpMyFAQ 3.1.16 +# phpMyFAQ 3.1.17 **Codename "Poseidon"** @@ -6,6 +6,11 @@ This is a log of major user-visible changes in each phpMyFAQ release. +### phpMyFAQ v3.1.17 - 2023-08-27 + +- fixed multiple security vulnerabilities (Thorsten) +- fixed minor bugs (Thorsten) + ### phpMyFAQ v3.1.16 - 2023-07-16 - fixed multiple security vulnerabilities (Thorsten) diff --git a/package.json b/package.json index 44aeaca810..ddaba5d1f5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thorsten/phpmyfaq", - "version": "3.1.16", + "version": "3.1.17", "description": "phpMyFAQ", "repository": "git://github.com/thorsten/phpMyFAQ.git", "author": "Thorsten Rinne", diff --git a/phpmyfaq/src/phpMyFAQ/System.php b/phpmyfaq/src/phpMyFAQ/System.php index b157079b1a..818aadc1a4 100644 --- a/phpmyfaq/src/phpMyFAQ/System.php +++ b/phpmyfaq/src/phpMyFAQ/System.php @@ -45,7 +45,7 @@ class System /** * Patch level. */ - private const VERSION_PATCH_LEVEL = 16; + private const VERSION_PATCH_LEVEL = 17; /** * Pre-release version. diff --git a/scripts/version.sh b/scripts/version.sh index e6f3489b5f..138951e0ee 100644 --- a/scripts/version.sh +++ b/scripts/version.sh @@ -1,4 +1,4 @@ #!/bin/sh if [ "x${PMF_VERSION}" = "x" ]; then - PMF_VERSION="3.1.16" + PMF_VERSION="3.1.17" fi From a707262ab28ef00972d4aebdbea3903dd8393ce3 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Sun, 27 Aug 2023 21:06:15 +0200 Subject: [PATCH 24/26] chore: hopefully the last RC --- CHANGELOG.md | 4 ++-- package.json | 2 +- phpmyfaq/src/phpMyFAQ/System.php | 2 +- scripts/version.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74e63d4c35..e168d5ad74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -# phpMyFAQ 3.2.0 +# phpMyFAQ 3.2.0-RC.4 **Codename "Pontus"** @@ -6,7 +6,7 @@ This is a log of major user-visible changes in each phpMyFAQ release. -### phpMyFAQ v3.2.0 - 2023-08- +### phpMyFAQ v3.2.0-RC.4 - 2023-08- - changed PHP requirement to PHP 8.1.0 or later (Thorsten) - changed to HTTPS as new default (Thorsten) diff --git a/package.json b/package.json index 9a1d9e574a..7d190bb07d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@thorsten/phpmyfaq", - "version": "3.2.0-RC.3", + "version": "3.2.0-RC.4", "description": "phpMyFAQ", "repository": "git://github.com/thorsten/phpMyFAQ.git", "author": "Thorsten Rinne", diff --git a/phpmyfaq/src/phpMyFAQ/System.php b/phpmyfaq/src/phpMyFAQ/System.php index fbea21eb12..24619dfe22 100644 --- a/phpmyfaq/src/phpMyFAQ/System.php +++ b/phpmyfaq/src/phpMyFAQ/System.php @@ -51,7 +51,7 @@ class System /** * Pre-release version. */ - private const VERSION_PRE_RELEASE = 'RC.3'; + private const VERSION_PRE_RELEASE = 'RC.4'; /** * API version. diff --git a/scripts/version.sh b/scripts/version.sh index 44b20d2c86..a015bd382f 100644 --- a/scripts/version.sh +++ b/scripts/version.sh @@ -1,4 +1,4 @@ #!/bin/sh if [ "x${PMF_VERSION}" = "x" ]; then - PMF_VERSION="3.2.0-RC.3" + PMF_VERSION="3.2.0-RC.4" fi From f584d8bf9ba9780da73a078f4cc7fd97685bfe8e Mon Sep 17 00:00:00 2001 From: sasama Date: Mon, 28 Aug 2023 14:57:28 +0900 Subject: [PATCH 25/26] Fix: faqdata_tags error --- phpmyfaq/src/phpMyFAQ/Tags.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/phpmyfaq/src/phpMyFAQ/Tags.php b/phpmyfaq/src/phpMyFAQ/Tags.php index 2f1a1049be..8d291ddc1a 100644 --- a/phpmyfaq/src/phpMyFAQ/Tags.php +++ b/phpmyfaq/src/phpMyFAQ/Tags.php @@ -110,6 +110,7 @@ public function getAllTagsById(int $recordId): array public function saveTags(int $recordId, array $tags): bool { $currentTags = $this->getAllTags(); + $registeredTags = []; // Delete all tag references for the faq record if (count($tags) > 0) { @@ -119,7 +120,7 @@ public function saveTags(int $recordId, array $tags): bool // Store tags and references for the faq record foreach ($tags as $tagName) { $tagName = trim($tagName); - if (Strings::strlen($tagName) > 0) { + if (Strings::strlen($tagName) > 0 && !in_array($tagName, $registeredTags, true)) { if ( !in_array( Strings::strtolower($tagName), @@ -156,6 +157,7 @@ public function saveTags(int $recordId, array $tags): bool ); } $this->config->getDb()->query($query); + $registeredTags[] = $tagName; } } From 66f15882273daa071fc4b8b4fa4dbb8d00b62f84 Mon Sep 17 00:00:00 2001 From: Thorsten Rinne Date: Tue, 29 Aug 2023 20:44:35 +0200 Subject: [PATCH 26/26] fix: allow data URIs in images, closes #2613 --- phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php | 1 + 1 file changed, 1 insertion(+) diff --git a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php index 6bb95d8bee..20c9b6733b 100644 --- a/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php +++ b/phpmyfaq/src/phpMyFAQ/Helper/FaqHelper.php @@ -261,6 +261,7 @@ public function cleanUpContent(string $content): string 'tags' => [ 'img' => [ 'allowed_attributes' => ['alt', 'class', 'height', 'src', 'style', 'title', 'width'], + 'allow_data_uri' => true ], 'div' => [ 'allowed_attributes' => ['class', 'style'],