diff --git a/src/server/i18n/de.php b/src/server/i18n/de.php index 8fb4493..231f2a3 100644 --- a/src/server/i18n/de.php +++ b/src/server/i18n/de.php @@ -4,6 +4,9 @@ $i18n = array( 'error.noJavaScript' => 'Bitte aktivieren Sie JavaScript in den Einstellungen Ihres Browser um diese Seite verwenden zu können.', 'error.browserNotSupported' => 'Ihr Browser wird nicht unterstützt. Bitte verwenden Sie einen aktuellen Browser.', 'error.errorLogged' => 'Es ist ein Fehler aufgetreten. Bitte prüfen Sie die Log-Datei.', + 'error.editingArticleFailed' => 'Der Artikel kann nicht bearbeitet werden.', + 'error.missingWritePermissions.article' => 'Der Server hat keine Schreibrechte für die Artikel-Datei:', + 'error.missingWritePermissions.backup' => 'Der Server hat keine Schreibrechte für die Backup-Datei:', 'button.cancel' => 'Abbrechen', 'button.back' => 'Zurück', 'button.edit' => 'Bearbeiten', diff --git a/src/server/i18n/en.php b/src/server/i18n/en.php index 3a59185..6534774 100644 --- a/src/server/i18n/en.php +++ b/src/server/i18n/en.php @@ -4,6 +4,9 @@ $i18n = array( 'error.noJavaScript' => 'Please activate JavaScript in the settings of your browser in order to use this site.', 'error.browserNotSupported' => 'Your browser is not supported. Please use an up-to-date browser.', 'error.errorLogged' => 'An error has occurred. Please have a look to the log file.', + 'error.editingArticleFailed' => 'Editing article failed.', + 'error.missingWritePermissions.article' => 'The server has no write permissions for the article file:', + 'error.missingWritePermissions.backup' => 'The server has no write permissions for the backup file:', 'button.cancel' => 'Cancel', 'button.back' => 'Back', 'button.edit' => 'Edit', diff --git a/src/server/layout/page.php b/src/server/layout/page.php index c816655..904449d 100644 --- a/src/server/layout/page.php +++ b/src/server/layout/page.php @@ -61,19 +61,24 @@ $mode = $data['mode']; if ($mode != 'view') { // Show an error message if JavaScript is off or if the browser is not supported. // NOTE: In view mode we don't show an error. Instead, syntax highlighting will be off for unsupported browsers. - ?>
- -
+ ?>
+ +
+ +
- + @@ -169,13 +174,15 @@ if ($mode == 'edit') { - + + + diff --git a/src/server/logic/EditorService.php b/src/server/logic/EditorService.php index a9b3fef..2a41bfe 100644 --- a/src/server/logic/EditorService.php +++ b/src/server/logic/EditorService.php @@ -36,6 +36,32 @@ class EditorService { } } + public function checkForError($articleFilename) { + function canWriteFileOrParent($filename) { + if ($filename == '') { + return false; + } else if (file_exists($filename)) { + return is_writable($filename); + } else { + return canWriteFileOrParent(dirname($filename)); + } + } + + $articleFullFilename = $this->context->getArticleBaseDir() . $articleFilename; + if (! canWriteFileOrParent($articleFullFilename)) { + return $this->context->getI18n()['error.missingWritePermissions.article'] + . ' ' . $articleFullFilename . ''; + } + + $backupFullFilename = $this->context->getDataBaseDir() . $this->getBackupFilename($articleFilename); + if (! canWriteFileOrParent($backupFullFilename)) { + return $this->context->getI18n()['error.missingWritePermissions.backup'] + . ' ' . $backupFullFilename . ''; + } + + return null; + } + public function saveArticle($articleFilename, $markdownText) { $this->assertLoggedIn(); @@ -43,23 +69,26 @@ class EditorService { throw new Exception("Invalid article filename: '$articleFilename'"); } - // Set timezone - $this->context->getConfig(); - // Write article file $articleFullFilename = $this->context->getArticleBaseDir() . $articleFilename; $articleDir = dirname($articleFullFilename); if (! file_exists($articleDir)) { mkdir($articleDir, 0777, true); } + if (! is_writable(file_exists($articleFullFilename) ? $articleFullFilename : $articleDir)) { + throw new Exception("No write permissions for article file"); + } file_put_contents($articleFullFilename, $markdownText); // Write backup file (one per day) - $backupFullFilename = $this->context->getDataBaseDir() . 'backup/' . $articleFilename . date('_Y-m-d') . '.gz'; + $backupFullFilename = $this->context->getDataBaseDir() . $this->getBackupFilename($articleFilename); $backupDir = dirname($backupFullFilename); if (! file_exists($backupDir)) { mkdir($backupDir, 0777, true); } + if (! is_writable(file_exists($backupFullFilename) ? $backupFullFilename : $backupDir)) { + throw new Exception("No write permissions for backup file"); + } $fp = gzopen ($backupFullFilename, 'w9'); gzwrite ($fp, $markdownText); gzclose($fp); @@ -67,6 +96,13 @@ class EditorService { return $this->context->getRenderService()->renderMarkdown($markdownText, true); } + private function getBackupFilename($articleFilename) { + // Set timezone + $this->context->getConfig(); + + return 'backup/' . $articleFilename . date('_Y-m-d') . '.gz'; + } + public function createUserConfig($user, $pass) { $type = 'sha256'; $salt = uniqid(mt_rand(), true); diff --git a/src/server/logic/Main.php b/src/server/logic/Main.php index 3e9c04d..cb9026d 100644 --- a/src/server/logic/Main.php +++ b/src/server/logic/Main.php @@ -58,8 +58,8 @@ class Main { try { $responseData['result'] = call_user_func_array(array($object, $methodName), $requestData['params']); } catch (Exception $exc) { - $msg = "Calling RPC $objectName.$methodName failed"; - error_log($msg . ': ' . $exc->getMessage()); + $msg = "Calling RPC $objectName.$methodName failed: " . $exc->getMessage(); + error_log($msg); $responseData['error'] = array( 'code' => -32000, 'message' => $msg ); } } @@ -102,10 +102,20 @@ class Main { } else { $config = $this->context->getConfig(); + $fatalErrorMessage = null; + if ($mode == 'edit') { + $fatalErrorMessage = $this->context->getEditorService()->checkForError($articleFilename); + if ($fatalErrorMessage != null) { + $fatalErrorMessage = $this->context->getI18n()['error.editingArticleFailed'] . '
' . $fatalErrorMessage; + $mode = 'error'; + } + } + $data = array(); $data['baseUrl'] = $baseUrl; $data['basePath'] = $basePath; $data['mode'] = $mode; + $data['fatalErrorMessage'] = $fatalErrorMessage; foreach (array('wikiName', 'footerHtml') as $key) { $data[$key] = $config[$key];