|
From: <re...@us...> - 2007-09-21 09:53:54
|
Revision: 563
http://sciret.svn.sourceforge.net/sciret/?rev=563&view=rev
Author: reinerj
Date: 2007-09-21 02:53:52 -0700 (Fri, 21 Sep 2007)
Log Message:
-----------
update the trunk to stable
Modified Paths:
--------------
trunk/CHANGELOG
trunk/CONTRIBUTORS
trunk/TODO
trunk/VERSION
trunk/actions/DeleteArticle.php
trunk/actions/EditUser.php
trunk/actions/Install.php
trunk/actions/Login.php
trunk/actions/MailArticle.php
trunk/actions/SaveArticle.php
trunk/actions/SaveCategory.php
trunk/actions/SavePreferences.php
trunk/actions/Upgrade.php
trunk/classes/Controller.php
trunk/fckeditor/editor/_source/classes/fckcontextmenu.js
trunk/fckeditor/editor/_source/classes/fckdataprocessor.js
trunk/fckeditor/editor/_source/classes/fckdomrange.js
trunk/fckeditor/editor/_source/classes/fckdomrange_gecko.js
trunk/fckeditor/editor/_source/classes/fckdomrange_ie.js
trunk/fckeditor/editor/_source/classes/fckeditingarea.js
trunk/fckeditor/editor/_source/classes/fckenterkey.js
trunk/fckeditor/editor/_source/classes/fckevents.js
trunk/fckeditor/editor/_source/classes/fckicon.js
trunk/fckeditor/editor/_source/classes/fckiecleanup.js
trunk/fckeditor/editor/_source/classes/fckkeystrokehandler.js
trunk/fckeditor/editor/_source/classes/fckpanel.js
trunk/fckeditor/editor/_source/classes/fckspecialcombo.js
trunk/fckeditor/editor/_source/classes/fcktoolbarbutton.js
trunk/fckeditor/editor/_source/classes/fcktoolbarfontformatcombo.js
trunk/fckeditor/editor/_source/classes/fcktoolbarstylecombo.js
trunk/fckeditor/editor/_source/commandclasses/fck_othercommands.js
trunk/fckeditor/editor/_source/commandclasses/fckfitwindow.js
trunk/fckeditor/editor/_source/commandclasses/fcktablecommand.js
trunk/fckeditor/editor/_source/fckeditorapi.js
trunk/fckeditor/editor/_source/fckscriptloader.js
trunk/fckeditor/editor/_source/internals/fck.js
trunk/fckeditor/editor/_source/internals/fck_contextmenu.js
trunk/fckeditor/editor/_source/internals/fck_gecko.js
trunk/fckeditor/editor/_source/internals/fck_ie.js
trunk/fckeditor/editor/_source/internals/fckcommands.js
trunk/fckeditor/editor/_source/internals/fckconfig.js
trunk/fckeditor/editor/_source/internals/fckdocumentprocessor.js
trunk/fckeditor/editor/_source/internals/fckdomtools.js
trunk/fckeditor/editor/_source/internals/fcklanguagemanager.js
trunk/fckeditor/editor/_source/internals/fcklistslib.js
trunk/fckeditor/editor/_source/internals/fckselection.js
trunk/fckeditor/editor/_source/internals/fckselection_gecko.js
trunk/fckeditor/editor/_source/internals/fckselection_ie.js
trunk/fckeditor/editor/_source/internals/fcktablehandler.js
trunk/fckeditor/editor/_source/internals/fcktoolbarset.js
trunk/fckeditor/editor/_source/internals/fcktools.js
trunk/fckeditor/editor/_source/internals/fcktools_gecko.js
trunk/fckeditor/editor/_source/internals/fcktools_ie.js
trunk/fckeditor/editor/_source/internals/fckxhtml.js
trunk/fckeditor/editor/_source/internals/fckxhtml_ie.js
trunk/fckeditor/editor/_source/internals/fckxhtmlentities.js
trunk/fckeditor/editor/dialog/fck_flash/fck_flash.js
trunk/fckeditor/editor/dialog/fck_image/fck_image.js
trunk/fckeditor/editor/dialog/fck_link/fck_link.js
trunk/fckeditor/editor/dialog/fck_paste.html
trunk/fckeditor/editor/dialog/fck_replace.html
trunk/fckeditor/editor/dialog/fck_smiley.html
trunk/fckeditor/editor/dialog/fck_specialchar.html
trunk/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm
trunk/fckeditor/editor/dialog/fck_tablecell.html
trunk/fckeditor/editor/fckdialog.html
trunk/fckeditor/editor/fckeditor.html
trunk/fckeditor/editor/filemanager/browser/default/browser.css
trunk/fckeditor/editor/filemanager/browser/default/browser.html
trunk/fckeditor/editor/filemanager/browser/default/frmfolders.html
trunk/fckeditor/editor/filemanager/browser/default/frmresourceslist.html
trunk/fckeditor/editor/filemanager/browser/default/frmupload.html
trunk/fckeditor/editor/lang/_translationstatus.txt
trunk/fckeditor/editor/lang/cs.js
trunk/fckeditor/editor/lang/en-au.js
trunk/fckeditor/editor/lang/en-ca.js
trunk/fckeditor/editor/lang/en-uk.js
trunk/fckeditor/editor/lang/en.js
trunk/fckeditor/editor/lang/fi.js
trunk/fckeditor/editor/lang/he.js
trunk/fckeditor/editor/lang/zh-cn.js
trunk/fckeditor/editor/lang/zh.js
trunk/fckeditor/editor/plugins/tablecommands/fckplugin.js
trunk/fckeditor/editor/skins/default/fck_dialog.css
trunk/fckeditor/editor/skins/default/fck_strip.gif
trunk/fckeditor/editor/skins/office2003/fck_dialog.css
trunk/fckeditor/editor/skins/office2003/fck_strip.gif
trunk/fckeditor/editor/skins/silver/fck_dialog.css
trunk/fckeditor/editor/skins/silver/fck_strip.gif
trunk/fckeditor/fckconfig.js
trunk/fckeditor/fckeditor.js
trunk/fckeditor/fckpackager.xml
trunk/flowMap.php
trunk/javascript/general.js
trunk/languages/ChineseTraditional.txt
trunk/languages/Czech.txt
trunk/languages/Deutsch.txt
trunk/languages/Dutch.txt
trunk/languages/English.txt
trunk/languages/Hebrew.txt
trunk/languages/Italian.txt
trunk/languages/Japanese.txt
trunk/languages/Norsk.txt
trunk/languages/Russian.txt
trunk/languages/Spanish.txt
trunk/languages/Svenska.txt
trunk/models/Article.php
trunk/models/ArticleGateway.php
trunk/models/ArticleIterator.php
trunk/models/Configuration.php
trunk/models/Question.php
trunk/models/User.php
trunk/models/UserGateway.php
trunk/setup/final.sql
trunk/setup/sampleData.sql
trunk/setup/versions.php
trunk/templates/EditArticle.tpl
trunk/templates/EditBookmark.tpl
trunk/templates/EditCategories.tpl
trunk/templates/EditCategory.tpl
trunk/templates/EditPreferences.tpl
trunk/templates/EditUser.tpl
trunk/templates/MainView.tpl
trunk/templates/RelatedArticles.tpl
trunk/templates/ViewArticle.tpl
trunk/templates/head.tpl
trunk/templates/header.tpl
trunk/views/EditArticle.php
trunk/views/EditCategories.php
trunk/views/EditPreferences.php
trunk/views/EditUser.php
trunk/views/InstallEnterCredentials.php
trunk/views/MainView.php
trunk/views/View.php
trunk/views/ViewArticle.php
trunk/views/ViewBookmark.php
Modified: trunk/CHANGELOG
===================================================================
--- trunk/CHANGELOG 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/CHANGELOG 2007-09-21 09:53:52 UTC (rev 563)
@@ -1,20 +1,124 @@
-2007-08-24 Lucie Goga <lg...@th...>
- * Add Italian translation from two students
+2007-09-21 Lucie Goga <lg...@th...>
+ * Sciret 1.2.0 release
-2007-07-18 Lucie Goga <lg...@th...>
- * Sciret 1.1.0
- * extention Send mail as UTF-8, patch reported from Rune Hammersland
+2007-09-03 Lucie Goga <lg...@th...>
+ * Sciret 1.2.0-RC1
+ * Sciret language packs 1.2.0
+2007-09-05 Alejandro Pedraza <ale...@gm...>
+ * [BUG] Fix in the upgrade fuction
+ getValidatedUser() needs the config array to need what version we're on
+
+2007-09-03 Lucie Goga <lg...@th...>
+ * update language file Russian, Spanish, Svenska.
+ * update Roadmap
+
+2007-09-02 Lucie Goga <lg...@th...>
+ * update language file Hebrew, Japanese, Italian, Norsk, Russian, Spanish.
+ The file are sorted and extended.
+
+2007-08-24 Lucie Goga <lg...@th...>
+ * Add Italian translation from two students
+ * update language file Chinesetraditional, Czech, Dutch.
+ The file are sorted and extended.
+
+2007-08-22 Lucie Goga <lg...@th...>
+ * Add SF patch 1778378 from Trond Viggo Håpnes. This patch
+ Restrict the possibility to modify and delete articles.
+ * update German lang file
+
+2007-08-22 Alejandro Pedraza <ale...@gm...>
+ * [BUG] Fix SF bug 1778175 Bookmark save as draft
+ * [BUG] Fix SF bug 1772632 Expiration Date in Bookmarks
+
+2007-08-20 Lucie Goga <lg...@th...>
+ * Update the English and German lang file.
+
+2007-08-19 Lucie Goga <lg...@th...>
+ * Update the English and German lang file.
+
+2007-08-19 Alejandro Pedraza <ale...@gm...>
+ * New feature: download pdf for article
+ * New feature: repeat password field to avoid typos
+ * SQL Error
+
+2007-08-18 Alejandro Pedraza <ale...@gm...>
+ * FCKEditor: Make the config a little smarter by figuring out itself
+ where the upload dir must go
+ * Added explanatory message to error list
+ * Killed ConfigNotWritable view. Show missing requirements in the view
+ where the db credentials are shown. Also have additional
+ checks: for db version and check if upload dirs are writable.
+
+2007-08-16 Reiner Jung <rj...@th...>
+ * Update the English and German lang file. Files are sorted now and
+ duplicates are removed
+
+2007-08-16 Lucie Goga <lg...@th...>
+ * release 1.2.0-svn-r487
+ * Add SF patch 1775353 from Trond Viggo Håpnes. This patch
+ allows / disallow coments and ratings.
+
+2007-08-16 Alejandro Pedraza <ale...@gm...>
+ * Allow users can manage the categories and hide them with the
+ Manage categories.
+
+2007-08-15 Lucie Goga <lg...@th...>
+ * [BUG] Add SF patch 1772600 from Trond Viggo Håpnes. This patch
+ allows the admin to remove the icon from a (sub)category.
+
+2007-08-13 Alejandro Pedraza <ale...@gm...>
+ * Show original question for articles that answer a question.
+ When an article was made to answer a question, show the
+ question text between the title and the article excerpt in
+ the list view, and between the title and the category in
+ the article detail view. Also, when an article that answers
+ a question is shown on the list view, use a question mark
+ as an icon, instead of the sheet icon currently used.
+ * update db structure
+
+2007-08-10 Reiner Jung <rj...@th...>
+ * Add SF patch 1765899 from Trond Viggo Håpnes. This patch removes
+ the mail-link from ViewArticle if the article is marked
+ for internal use only
+ * Fixed a typing error in EditArticle.tpl
+
+2007-08-04 Alejandro Pedraza <ale...@gm...>
+ * Let registered users edit their own profile.
+ * Added functionality to expire passwords and oblige users to
+ change them when that happens
+ * Be able to decide whether the KB is public or not
+ (set by the admin, in the preferences section)
+
+2007-08-02 Reiner Jung <rj...@th...>
+ * Add SF patch 1771482 from Trond Viggo Håpnes. This patch will
+ let the administrator decide if new articles should be marked
+ for internal or public use. Only the administrator can change
+ status on an article from internal to public. You can not email
+ an article marked for internal use only.
+
+2007-07-28 Reiner Jung <rj...@th...>
+ * Update the setup scripts for Sciret 1.2.0
+ * Add SF patch 1762272 from Rune Hammersland. This patch enables
+ the admin to choose between sending e-mails through sendmail or
+ through an SMTP server of his choosing. The admin can also
+ choose the name and address used when sending e-mails.
+ * Update language files for SMTP settings
+ * Update Norsk translation
+
+2007-07-23 Reiner Jung <rj...@th...>
+ * Add XCache to the Sciret documentation. OpenBSD howto is still
+ missing with xcache
+
+2007-07-18 Lucie Goga <lg...@th...>
+ * Sciret 1.1.0 release
+
2007-07-15 Alejandro Pedraza <ale...@gm...>
* [BUG] Fix problem to send mail from Sciret
2007-07-12 Lucie Goga <lg...@th...>
* Add Norwegian translation from Rune Hammersland
-2007-07-10 Reiner Jung <rj...@th...>
- * [BUG] Fix a problem that saving a draft article didn't appear
- in the unpublished and drafts list
-
2007-06-29 Reiner Jung <rj...@th...>
* update scriptulus to last version
Modified: trunk/CONTRIBUTORS
===================================================================
--- trunk/CONTRIBUTORS 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/CONTRIBUTORS 2007-09-21 09:53:52 UTC (rev 563)
@@ -1,9 +1,10 @@
Contributors to Sciret development
-
Patch contribution
* Nikolai Essel submitted patches to sciret 0.9 and 1.1
+ * Rune Hammersland submitted patches to sciret 1.1 and 1.2
+ * Trond Viggo Håpnes submitted patches to sciret 1.2
Translations
@@ -11,7 +12,7 @@
* Dutch translation R. de Milde
* Hebrew translation from SF user Golanor
* Japanese translation from SF user tm800720
- * Norwegian translation from Rune Hammersland
+ * Norway translation from Rune Hammersland
* Swedish translation from Henrik Christensson
Testing
Modified: trunk/TODO
===================================================================
--- trunk/TODO 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/TODO 2007-09-21 09:53:52 UTC (rev 563)
@@ -1,30 +1,27 @@
-1.2 Release
-- When edit a category and select a icon, the icon should be visible as a preview and not after it is selected
-- Password protected access to Sciret that only signed in users have access. Should be a configuration option (SF request 1704597)
-- A Question should be visible also in the categories where the question is assigned so long as it is answered. It must be marked
- that it is clear visible this is a question
-- Automatic password reset for users (SF request 1704597)
-- Preferences for a user based view of the screen
-- Pre Installation check for Sciret (Check the right file system rights ...)
-
1.3 Release
-- New User Interface for Sciret based on the work from Nuno Pinheiro
+- Introduce group support. Admin can restrict access to User based work groups
+- Search for articles by registerd users
+- Make an article appear in more than one category
+- Add tags and tag search to article, bookmarks and documents
+- Admin must change the default password after first login
1.4 Release
-- Document Management Functionality
-- Add tags and tag search to article, bookmarks and documents
+- New User Interface for Sciret based on the work from Nuno Pinheiro
- Ubuntu/Debian Packages
+- Cancel Editing
+- Send mail as PDF
1.5 Release
-- Introduce group support. Groups from admin for restricrted access and User based work groups
-- Create PDF from Article
+- Document Management Functionality
+- A category will be only visible when there is a article or bookmark in. Otherwise it will be hidden
- Authentication again LDAP
- Authentication again AD
1.6 Release
- One Time Passwords
- Authentication with Secure Token
-- Search for articles by registered users
+- Category Content [Feature RQID 1776663]
+- What links here [Feature RQ ID 1776661]
1.7 Release
- Sciret will use PHPUnit testing. This will delay our further releases, but will give it more stability
Modified: trunk/VERSION
===================================================================
--- trunk/VERSION 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/VERSION 2007-09-21 09:53:52 UTC (rev 563)
@@ -1 +1 @@
-1.1.0-SVN-Release-428
+1.2.0-SVN-Release-554
Modified: trunk/actions/DeleteArticle.php
===================================================================
--- trunk/actions/DeleteArticle.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/DeleteArticle.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -17,6 +17,15 @@
function dispatch() {
$artId = isset($_GET['id'])? (int)$_GET['id'] : 0;
+ if ($this->configuration->getConfigValue('restrictEditDelete')) {
+ $article = new Article($artId);
+
+ if ($article->getUserId() != $this->user->getId() && ($this->user->getRole() & ROLE_ADMIN) != ROLE_ADMIN) {
+ $_SESSION['message'] = $this->user->lang('Sorry, only the author or an admin can delete this article.');
+ Library::redirect(Library::getLink(array('view' => 'ViewArticle', 'id' => $artId)));
+ }
+ }
+
$articleGateway = new ArticleGateway;
$articleGateway->delete($artId);
Modified: trunk/actions/EditUser.php
===================================================================
--- trunk/actions/EditUser.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/EditUser.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -15,6 +15,13 @@
class EditUser extends Action {
function dispatch() {
+
+ // security check
+ if (!$this->user->isAdmin() && $this->user->getId() != $_POST['userId']) {
+ $_SESSION['message'] = $this->user->lang('What are you trying to do??');
+ Library::redirect(Library::getLink(array('view' => 'Login')));
+ }
+
$userId = (int)$_POST['userId'];
$user = new User($userId);
@@ -36,18 +43,21 @@
$missingFieldsArr[] = $this->user->lang('password');
}
- if (!$user->setPassword($_POST['password'])) {
+ $invalidPassword = false;
+ if ($_POST['password'] != $_POST['password2']) {
+ $_SESSION['message'] = $this->user->lang('Password and Repeat Password fields don\'t match');
+ $invalidPassword = true;
+ }
+ elseif (!$user->setPassword($_POST['password'])) {
$_SESSION['message'] = $this->user->lang('Invalid password. Please don\'t use any of these characters: %s', implode($user->getDisallowedPasswordChars()));
$invalidPassword = true;
- } else {
- $invalidPassword = false;
}
if ($missingFieldsArr) {
$_SESSION['message'] = $this->user->lang('You need to fill the following fields: ').implode(', ', $missingFieldsArr);
}
- if ($missingFields || $invalidPassword) {
+ if ($missingFieldsArr || $invalidPassword) {
$_SESSION['formFields'] = array(
'firstName' => $_POST['firstName'],
'lastName' => $_POST['lastName'],
@@ -60,19 +70,30 @@
}
} else {
- if ($_POST['password'] != '') {
- if (!$user->changePassword($_POST['password'])) {
- $_SESSION['message'] = $this->user->lang('Invalid password. Please don\'t use any of these characters: %s', implode(', ', $user->getDisallowedPasswordChars()));
+
+ if (
+ $user->isPasswordExpired($this->configuration->getConfigValue('passwordExpirationDays'))
+ && $user->getPassword() == md5($_POST['password'])
+ )
+ {
+ $_SESSION['message'] = $this->user->lang('Your password has expired. Please change it below.');
Library::redirect(Library::getLink(array('view' => 'EditUser', 'userId' => $user->getId())));
- }
}
+
+ if ($_POST['password'] != $_POST['password2']) {
+ $_SESSION['message'] = $this->user->lang('Password and Repeat Password fields don\'t match');
+ Library::redirect(Library::getLink(array('view' => 'EditUser', 'userId' => $user->getId())));
+ } elseif (!$user->changePassword($_POST['password'])) {
+ $_SESSION['message'] = $this->user->lang('Invalid password. Please don\'t use any of these characters: %s', implode(', ', $user->getDisallowedPasswordChars()));
+ Library::redirect(Library::getLink(array('view' => 'EditUser', 'userId' => $user->getId())));
+ }
}
$user->setFirstName($_POST['firstName']);
$user->setLastName($_POST['lastName']);
$user->setUserName($_POST['userName']);
$user->setEmail($_POST['email']);
- $user->setAdmin(isset($_POST['adminAccess']));
+ $user->setAdmin($this->user->isAdmin() && isset($_POST['adminAccess']));
$user->save();
if (!$user->getId()) {
@@ -80,7 +101,12 @@
} else {
$_SESSION['message'] = $this->user->lang('User edited successfully');
}
- Library::redirect(Library::getLink(array('view' => 'ManageUsers')));
+
+ if ($this->user->isAdmin()) {
+ Library::redirect(Library::getLink(array('view' => 'ManageUsers')));
+ } else {
+ Library::redirect(Library::getLink(array('view' => 'EditUser', 'userId' => $user->getId())));
+ }
}
}
Modified: trunk/actions/Install.php
===================================================================
--- trunk/actions/Install.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/Install.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -17,13 +17,6 @@
function dispatch() {
- // is_writable() not working under windows
- if (!$fp = @fopen(dirname(__FILE__).'/../config.php', 'a')) {
- Library::redirect(Library::getLink(array('view' => 'ConfigNotWritable')));
- } else {
- fclose($fp);
- }
-
if (!isset($_GET['step'])) {
$_GET['step'] = 0;
}
@@ -35,17 +28,35 @@
case 1:
$this->db =& DB::DBFactory(DB_ENGINE, $_POST['host'], $_POST['username'], $_POST['password'], true);
if (!$this->db->connect()) {
- Library::redirect(Library::getLink(array('view' => 'InstallEnterCredentials', 'error' => urlencode($this->user->lang('Couldn\'t connect to database')))));
+ Library::redirect(Library::getLink(array('view' => 'InstallEnterCredentials', 'error' => urlencode($this->user->lang('Couldn\'t connect to database, please check your credentials.')))));
}
+
+ $errors = array();
+ if (!$this->_isConfigWritable()) {
+ $errors[] = $this->user->lang('The config.php file must be writable');
+ }
+ if (!$this->_areUploadDirsWritable()) {
+ $errors[] = $this->user->lang('All directories under the "uploads" and "uploads/editor" directories must be writable');
+ }
+ if ($this->db->isLowerThan41()) {
+ $errors[] = $this->user->lang('You need a MySQL version no lower than 4.1');
+ }
+
if (!$this->db->selectDb($_POST['database'])) {
if (!$result = $this->db->createDB($_POST['database'])) {
- Library::redirect(Library::getLink(array('view' => 'InstallEnterCredentials', 'error' => urlencode($this->user->lang('Couldn\'t create database. Please create it manually and try again.')))));
+ $errors[] = $this->user->lang('Couldn\'t create database. Please create it manually and try again.');
+ } else {
+ $this->db->selectDb($_POST['database']);
}
- $this->db->selectDb($_POST['database']);
}
+
+ if ($errors) {
+ Library::redirect(Library::getLink(array('view' => 'InstallEnterCredentials', 'error' => urlencode(implode('<br />', $errors)))));
+ }
+
$this->_writeConfig(DB_ENGINE, $_POST['host'], $_POST['database'], $_POST['username'], $_POST['password']);
$this->_runSQLFILE('final.sql');
- if (isset($_POST['demodata'])) {
+ if (isset($_POST['demodata']) && $_POST['demodata']) {
$this->_runSQLFILE('sampleData.sql');
}
Library::redirect(Library::getLink(array('view' => 'InstallOk')));
@@ -101,6 +112,31 @@
}
fclose($fp);
}
+
+ function _isConfigWritable() {
+ // is_writable() not working under windows
+ if (!$fp = @fopen(dirname(__FILE__).'/../config.php', 'a')) {
+ return false;
+ }
+ fclose($fp);
+
+ return true;
+ }
+
+ function _areUploadDirsWritable() {
+ foreach (array('files', 'icons', 'editor/File', 'editor/Flash', 'editor/Image', 'editor/Media') as $folder) {
+ // is_writable() not working under windows
+ if (!$fp = @fopen(dirname(__FILE__)."/../uploads/$folder/eraseme.txt", 'a')) {
+ return false;
+ } else {
+ fclose($fp);
+ unlink(dirname(__FILE__)."/../uploads/$folder/eraseme.txt");
+ }
+
+ }
+
+ return true;
+ }
}
?>
Modified: trunk/actions/Login.php
===================================================================
--- trunk/actions/Login.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/Login.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -16,12 +16,18 @@
function dispatch() {
require 'models/UserGateway.php';
$userGateway = new UserGateway;
- if (!$user = $userGateway->getValidatedUser($_POST['username'], $_POST['password'])) {
+ if (!$user = $userGateway->getValidatedUser($_POST['username'], $_POST['password'], $this->configuration)) {
$_SESSION['message'] = $this->user->lang('Wrong Username or Password');
Library::redirect(Library::getLink(array('view' => 'Login')));
}
$_SESSION['userId'] = $user->getId();
+
+ if ($user->isPasswordExpired($this->configuration->getConfigValue('passwordExpirationDays'))) {
+ $_SESSION['message'] = $this->user->lang('Your password has expired. Please change it below.');
+ Library::redirect(Library::getLink(array('view' => 'EditUser', 'userId' => $user->getId())));
+ }
+
Library::redirect(Library::getLink(array('view' => 'MainView')));
}
}
Modified: trunk/actions/MailArticle.php
===================================================================
--- trunk/actions/MailArticle.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/MailArticle.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -23,7 +23,10 @@
if (!$article->getId()) {
die($this->user->lang('Invalid article ID'));
}
-
+ if ($article->isInternal()) {
+ $_SESSION['message'] = $this->user->lang('Sorry, this article is for internal use only.');
+ Library::redirect(Library::getLink(array('view' => 'ViewArticle', 'id' => $articleId)));
+ }
if ($_POST['recipient'] == '' || !preg_match($this->regexp_valid_email, $_POST['recipient'])) {
$_SESSION['message'] = $this->user->lang('Invalid recipient');
Library::redirect(Library::getLink(array('view' => 'MailArticle', 'artId' => $articleId)));
@@ -33,9 +36,8 @@
Library::redirect(Library::getLink(array('view' => 'MailArticle', 'artId' => $articleId)));
}
- $mail = new PHPMailer();
- $mail->IsSendmail();
- $mail->CharSet = "utf-8";
+ $mail = $this->setUpMailer();
+
if ($_POST['replyTo'] != '') {
$mail->AddReplyTo($_POST['replyTo']);
}
@@ -58,6 +60,30 @@
$_SESSION['message'] = $this->user->lang('E-mail has been successfuly sent');
Library::redirect(Library::getLink(array('view' => 'ViewArticle', 'id' => $articleId)));
}
+
+ function setUpMailer() {
+ $mail = new PHPMailer();
+
+ $config = $this->configuration;
+ $transport = $config->getConfigValue('mailTransport');
+
+ if ($transport == 'smtp') {
+ $mail->IsSMTP();
+ $mail->Host = $config->getConfigValue('smtpServer');
+ $mail->Username = $config->getConfigValue('smtpUser');
+ $mail->Password = $config->getConfigValue('smtpPassword');
+ $mail->Port = $config->getConfigValue('smtpPort');
+ } else if ($transport == 'sendmail') {
+ $mail->IsSendmail();
+ }
+
+ $mail->CharSet = "utf-8";
+ $mail->FromName = $config->getConfigValue('mailFromName');
+ $mail->From = $config->getConfigValue('mailFromMail');
+
+ return $mail;
+ }
+
}
?>
Modified: trunk/actions/SaveArticle.php
===================================================================
--- trunk/actions/SaveArticle.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/SaveArticle.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -17,6 +17,15 @@
function dispatch() {
$articleId = isset($_POST['articleId'])? (int)$_POST['articleId'] : 0;
+ if ($articleId > 0 && $this->configuration->getConfigValue('restrictEditDelete')) {
+ $article = new Article($articleId);
+
+ if ($article->getUserId() != $this->user->getId() && ($this->user->getRole() & ROLE_ADMIN) != ROLE_ADMIN) {
+ $_SESSION['message'] = $this->user->lang('Sorry, only the author or an admin can modify this article.');
+ Library::redirect(Library::getLink(array('view' => 'ViewArticle', 'id' => $articleId)));
+ }
+ }
+
// validation
if ($_POST['title'] == '') {
$_SESSION['message'] = $this->user->lang('Article can\'t be saved without a title.');
@@ -28,6 +37,12 @@
$art->setTitle($_POST['title']);
$art->setContent($_POST['content']);
+ if (!isset($_POST['usage_id'])) {
+ $art->setInternal($this->configuration->getConfigValue('internalByDefault')? 1 : 0);
+ } else {
+ $art->setInternal($_POST['usage_id']);
+ }
+
if ($_POST['expDate'] == '') {
$art->setExpDate('0000-00-00');
} else {
@@ -39,14 +54,15 @@
$art->setModifiedByUserId($this->user->getId());
$historyMessage = $this->user->lang('Article modified');
} else {
- $art->setPublished(($this->configuration->getConfigValue('publishArticlesAuto') == '1' && $_POST['draft'] != 1)? true : false);
+ $art->setPublished($this->configuration->getConfigValue('publishArticlesAuto') == '1'? true : false);
$art->setUserId($this->user->getId());
$historyMessage = $this->user->lang('Article created');
if (isset($_POST['questionID'])) {
- require 'models/QuestionGateway.php';
- $questionGateway = new QuestionGateway;
- $questionGateway->delete($_POST['questionID']);
+ require 'models/Question.php';
+ $question = new Question($_POST['questionID']);
+ $art->setQuestion($question->getContents());
+ $question->delete();
}
}
$art->setDraft($_POST['draft']);
Modified: trunk/actions/SaveCategory.php
===================================================================
--- trunk/actions/SaveCategory.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/SaveCategory.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -26,9 +26,7 @@
$category->setParentId($_POST['parentCategory']);
$category->setLabel($_POST['name']);
$category->setDescription($_POST['description']);
- if ($_POST['icon'] != 'blank.gif') {
- $category->setIconFileName($_POST['icon']);
- }
+ $category->setIconFileName($_POST['icon']);
$category->save();
$_SESSION['message'] = $this->user->lang('Category saved successfully');
Modified: trunk/actions/SavePreferences.php
===================================================================
--- trunk/actions/SavePreferences.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/SavePreferences.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -33,10 +33,22 @@
}
if (($this->user->getRole() & ROLE_ADMIN) == ROLE_ADMIN) {
+ $this->configuration->setConfigValue('publishKB', $_POST['publishKB'] == '1'? '1' : '0');
$this->configuration->setConfigValue('publishArticlesAuto', $_POST['publishArticlesAuto'] == '1'? '1' : '0');
$this->configuration->setConfigValue('publishBookmarksAuto', $_POST['publishBookmarksAuto'] == '1'? '1' : '0');
$this->configuration->setConfigValue('publishCommentsAuto', $_POST['publishCommentsAuto'] == '1'? '1' : '0');
$this->configuration->setConfigValue('publishQuestionsAuto', $_POST['publishQuestionsAuto'] == '1'? '1' : '0');
+ $this->configuration->setConfigValue('internalByDefault', $_POST['internalByDefault'] == '1'? '1' : '0');
+ $this->configuration->setConfigValue('allowCommentsRatings', $_POST['allowCommentsRatings'] == '1'? '1' : '0');
+ $this->configuration->setConfigValue('restrictEditDelete', $_POST['restrictEditDelete'] == '1'? '1' : '0');
+ $this->configuration->setConfigValue('passwordExpirationDays', $_POST['passwordExpirationDays']);
+ $this->configuration->setConfigValue('mailTransport', $_POST['mailTransport'] == 'smtp' ? 'smtp' : 'sendmail');
+ $this->configuration->setConfigValue('mailFromName', $_POST['mailFromName']);
+ $this->configuration->setConfigValue('mailFromMail', $_POST['mailFromMail']);
+ $this->configuration->setConfigValue('smtpServer', $_POST['smtpServer']);
+ $this->configuration->setConfigValue('smtpUser', $_POST['smtpUser']);
+ $this->configuration->setConfigValue('smtpPassword', $_POST['smtpPassword']);
+ $this->configuration->setConfigValue('smtpPort', $_POST['smtpPort']);
$this->configuration->save();
}
Modified: trunk/actions/Upgrade.php
===================================================================
--- trunk/actions/Upgrade.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/actions/Upgrade.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -17,7 +17,7 @@
function dispatch() {
require 'models/UserGateway.php';
$this->userGateway = new UserGateway;
- if (!($user = $this->userGateway->getValidatedUser($_POST['username'], $_POST['password'])) || !$user->isAdmin()) {
+ if (!($user = $this->userGateway->getValidatedUser($_POST['username'], $_POST['password'], $this->configuration)) || !$user->isAdmin()) {
$_SESSION['message'] = $this->user->lang('Wrong Username or Password');
Library::redirect(Library::getLink(array('view' => 'Upgrade')));
}
Modified: trunk/classes/Controller.php
===================================================================
--- trunk/classes/Controller.php 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/classes/Controller.php 2007-09-21 09:53:52 UTC (rev 563)
@@ -12,6 +12,8 @@
define('MINIMUM_ROLE', 0);
define('LOAD_CONFIGURATION', 1);
define('SHOW_HEADER', 2);
+define('ALLOW_VIEW_ONLY_IF_PUBLIC_KB', 3);
+define('ALLOW_ACTION_ONLY_IF_PUBLIC_KB', 2);
require 'models/Configuration.php';
@@ -52,7 +54,14 @@
$this->user->setSkipTranslations(true);
}
- if (($this->user->getRole() & $this->views[$view][MINIMUM_ROLE]) != $this->views[$view][MINIMUM_ROLE]) {
+ if (
+ // user hasn't got enough privileges
+ (($this->user->getRole() & $this->views[$view][MINIMUM_ROLE]) != $this->views[$view][MINIMUM_ROLE])
+
+ // or user is anonymous and KB is not public
+ || ($this->user->getRole() == ROLE_ANONYMOUS && $this->views[$view][ALLOW_VIEW_ONLY_IF_PUBLIC_KB] && !$this->configuration->getConfigValue('publishKB'))
+ )
+ {
Library::redirect(Library::getLink(array('view' => 'Login')));
}
require "views/$view.php";
Modified: trunk/fckeditor/editor/_source/classes/fckcontextmenu.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckcontextmenu.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckcontextmenu.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -94,9 +94,11 @@
FCKTools.CancelEvent( e ) ;
FCKContextMenu_AttachedElement_OnContextMenu( e, el._FCKContextMenu, el ) ;
+ return false ;
}
el = el.parentNode ;
}
+ return true ;
}
function FCKContextMenu_AttachedElement_OnContextMenu( ev, fckContextMenu, el )
@@ -140,4 +142,4 @@
{
contextMenu._Panel.Hide() ;
FCKTools.RunFunction( contextMenu.OnItemClick, contextMenu, menuItem ) ;
-}
\ No newline at end of file
+}
Modified: trunk/fckeditor/editor/_source/classes/fckdataprocessor.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckdataprocessor.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckdataprocessor.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -79,16 +79,8 @@
if ( FCKBrowserInfo.IsIE && FCKConfig.DocType.length > 0 && !FCKRegexLib.Html4DocType.test( FCKConfig.DocType ) )
html += ' style="overflow-y: scroll"' ;
- html += '><head><title></title></head><body' ;
-
- // Add id and class to the body.
- if ( FCKConfig.BodyId.length > 0 )
- html += ' id="' + FCKConfig.BodyId + '"' ;
- if ( FCKConfig.BodyClass.length > 0 )
- html += ' class="' + FCKConfig.BodyClass + '"' ;
-
- html +=
- '>' +
+ html += '><head><title></title></head>' +
+ '<body' + FCKConfig.GetBodyAttributes() + '>' +
data +
'</body></html>' ;
Modified: trunk/fckeditor/editor/_source/classes/fckdomrange.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckdomrange.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckdomrange.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -276,6 +276,71 @@
this._UpdateElementInfo() ;
},
+ // Non-intrusive bookmark algorithm
+ CreateBookmark2 : function()
+ {
+ // If there is no range then get out of here.
+ // It happens on initial load in Safari #962 and if the editor it's hidden also in Firefox
+ if ( ! this._Range )
+ return { "Start" : 0, "End" : 0 } ;
+
+ // First, we record down the offset values
+ var bookmark =
+ {
+ "Start" : [ this._Range.startOffset ],
+ "End" : [ this._Range.endOffset ]
+ } ;
+ // Then, we record down the precise position of the container nodes
+ // by walking up the DOM tree and counting their childNode index
+ var curNode = this._Range.startContainer ;
+ while ( curNode && curNode != this.Window.document.documentElement )
+ {
+ var curParent = curNode.parentNode ;
+ for( var i = 0 ; i < curParent.childNodes.length ; i++ )
+ {
+ if ( curParent.childNodes.item( i ) == curNode )
+ {
+ bookmark.Start.unshift( i ) ;
+ break ;
+ }
+ }
+ curNode = curParent;
+ }
+ curNode = this._Range.endContainer;
+ while ( curNode && curNode != this.Window.document.documentElement )
+ {
+ var curParent = curNode.parentNode;
+ for ( var i = 0 ; i < curParent.childNodes.length ; i++ )
+ {
+ if ( curParent.childNodes.item( i ) == curNode )
+ {
+ bookmark.End.unshift( i );
+ break;
+ }
+ }
+ curNode = curParent;
+ }
+ return bookmark;
+ },
+
+ MoveToBookmark2 : function( bookmark )
+ {
+ // Reverse the childNode counting algorithm in CreateBookmark2()
+ var curStart = this.Window.document.documentElement ;
+ var curEnd = this.Window.document.documentElement ;
+ for ( var i = 0 ; i < bookmark.Start.length - 1 ; i++ )
+ curStart = curStart.childNodes.item( bookmark.Start[ i ] ) ;
+ for ( var i = 0 ; i < bookmark.End.length - 1 ; i++ )
+ curEnd = curEnd.childNodes.item( bookmark.End[ i ] ) ;
+
+ // Generate the W3C Range object and update relevant data
+ this.Release( true ) ;
+ this._Range = new FCKW3CRange( this.Window.document ) ;
+ this._Range.setStart( curStart, bookmark.Start[ bookmark.Start.length - 1 ] ) ;
+ this._Range.setEnd( curEnd, bookmark.End[ bookmark.End.length - 1 ] ) ;
+ this._UpdateElementInfo() ;
+ },
+
MoveToPosition : function( targetElement, position )
{
this.SetStart( targetElement, position ) ;
@@ -570,4 +635,20 @@
this.EndBlockLimit = null ;
this._Range = null ;
}
-} ;
\ No newline at end of file
+} ;
+
+FCKDomRange.CompareCursors = function( cursor1, cursor2 )
+{
+ for ( var i = 0 ; i < Math.min( cursor1.length, cursor2.length ) ; i++ )
+ {
+ if ( cursor1[i] < cursor2[i] )
+ return -1;
+ else if (cursor1[i] > cursor2[i] )
+ return 1;
+ }
+ if ( cursor1.length < cursor2.length )
+ return -1;
+ else if (cursor1.length > cursor2.length )
+ return 1;
+ return 0;
+}
Modified: trunk/fckeditor/editor/_source/classes/fckdomrange_gecko.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckdomrange_gecko.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckdomrange_gecko.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -29,7 +29,7 @@
var oSel = this.Window.getSelection() ;
- if ( oSel.rangeCount == 1 )
+ if ( oSel && oSel.rangeCount > 0 )
{
this._Range = FCKW3CRange.CreateFromRange( this.Window.document, oSel.getRangeAt(0) ) ;
this._UpdateElementInfo() ;
Modified: trunk/fckeditor/editor/_source/classes/fckdomrange_ie.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckdomrange_ie.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckdomrange_ie.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -33,15 +33,24 @@
if ( oSel.type != 'Control' )
{
+ var eMarkerStart = this._GetSelectionMarkerTag( true ) ;
+ var eMarkerEnd = this._GetSelectionMarkerTag( false ) ;
+
+ if ( ! ( eMarkerStart && eMarkerEnd ) )
+ {
+ this._Range.setStart( this.Window.document.body, 0 );
+ this._Range.collapse( true );
+ this._UpdateElementInfo();
+ return;
+ }
+
// Set the start boundary.
- eMarker = this._GetSelectionMarkerTag( true ) ;
- this._Range.setStart( eMarker.parentNode, FCKDomTools.GetIndexOf( eMarker ) ) ;
- eMarker.parentNode.removeChild( eMarker ) ;
+ this._Range.setStart( eMarkerStart.parentNode, FCKDomTools.GetIndexOf( eMarkerStart ) ) ;
+ eMarkerStart.parentNode.removeChild( eMarkerStart ) ;
// Set the end boundary.
- var eMarker = this._GetSelectionMarkerTag( false ) ;
- this._Range.setEnd( eMarker.parentNode, FCKDomTools.GetIndexOf( eMarker ) ) ;
- eMarker.parentNode.removeChild( eMarker ) ;
+ this._Range.setEnd( eMarkerEnd.parentNode, FCKDomTools.GetIndexOf( eMarkerEnd ) ) ;
+ eMarkerEnd.parentNode.removeChild( eMarkerEnd ) ;
this._UpdateElementInfo() ;
}
@@ -122,6 +131,12 @@
var oRange = this.Window.document.selection.createRange() ;
oRange.collapse( toStart === true ) ;
+ // IE might take the range object to the main window instead of inside the editor iframe window.
+ // This is known to happen when the editor window has not been selected before (See #933).
+ // We need to avoid that.
+ if (oRange.parentElement().document != this.Window.document)
+ return null;
+
// Paste a marker element at the collapsed range and get it from the DOM.
var sMarkerId = 'fck_dom_range_temp_' + (new Date()).valueOf() + '_' + Math.floor(Math.random()*1000) ;
oRange.pasteHTML( '<span id="' + sMarkerId + '"></span>' ) ;
@@ -146,4 +161,4 @@
oRange.insertNode( eSpan ) ;
return eSpan ;
-}
\ No newline at end of file
+}
Modified: trunk/fckeditor/editor/_source/classes/fckeditingarea.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckeditingarea.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckeditingarea.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -52,7 +52,12 @@
{
// Create the editing area IFRAME.
var oIFrame = this.IFrame = oTargetDocument.createElement( 'iframe' ) ;
- oIFrame.src = 'javascript:void(0)' ;
+
+ // Firefox will render the tables inside the body in Quirks mode if the
+ // source of the iframe is set to javascript. see #515
+ if ( !FCKBrowserInfo.IsGecko )
+ oIFrame.src = 'javascript:void(0)' ;
+
oIFrame.frameBorder = 0 ;
oIFrame.width = oIFrame.height = '100%' ;
@@ -130,6 +135,8 @@
eTextarea.dir = 'ltr' ;
eTextarea.style.width = eTextarea.style.height = '100%' ;
eTextarea.style.border = 'none' ;
+ // CSS3 http://www.w3.org/TR/css3-ui/#resize
+ eTextarea.style.resize = 'none' ;
eTargetElement.appendChild( eTextarea ) ;
eTextarea.value = html ;
@@ -162,7 +169,13 @@
if ( FCKBrowserInfo.IsIE )
{
+ oDoc.body.unselectable = "on" ;
oDoc.body.contentEditable = true ;
+ var enableFunc = function()
+ {
+ oDoc.body.removeAttribute("unselectable") ;
+ }
+ setTimeout( enableFunc, 1 ) ;
/* The following commands don't throw errors, but have no effect.
oDoc.execCommand( 'AutoDetect', false, false ) ;
@@ -208,10 +221,42 @@
// Disable the standard table editing features of Firefox.
oDoc.execCommand( 'enableInlineTableEditing', false, !FCKConfig.DisableFFTableHandles ) ;
}
- catch (e) {}
+ catch (e)
+ {
+ // In Firefox if the iframe is initially hidden it can't be set to designMode and it raises an exception
+ // So we set up a DOM Mutation event Listener on the HTML, as it will raise several events when the document is visible again
+ FCKTools.AddEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ;
+ }
+
}
}
+// This function processes the notifications of the DOM Mutation event on the document
+// We use it to know that the document will be ready to be editable again (or we hope so)
+function FCKEditingArea_Document_AttributeNodeModified( evt )
+{
+ var editingArea = evt.currentTarget.contentWindow._FCKEditingArea ;
+
+ // We want to run our function after the events no longer fire, so we can know that it's a stable situation
+ if ( editingArea._timer )
+ window.clearTimeout( editingArea._timer ) ;
+
+ editingArea._timer = FCKTools.SetTimeout( FCKEditingArea_MakeEditableByMutation, 1000, editingArea ) ;
+}
+
+// This function ideally should be called after the document is visible, it does clean up of the
+// mutation tracking and tries again to make the area editable.
+function FCKEditingArea_MakeEditableByMutation()
+{
+ // Clean up
+ delete this._timer ;
+ // Now we don't want to keep on getting this event
+ FCKTools.RemoveEventListener( this.Window.frameElement, 'DOMAttrModified', FCKEditingArea_Document_AttributeNodeModified ) ;
+ // Let's try now to set the editing area editable
+ // If it fails it will set up the Mutation Listener again automatically
+ this.MakeEditable() ;
+}
+
FCKEditingArea.prototype.Focus = function()
{
try
@@ -221,13 +266,21 @@
// The following check is important to avoid IE entering in a focus loop. Ref:
// http://sourceforge.net/tracker/index.php?func=detail&aid=1567060&group_id=75348&atid=543653
if ( FCKBrowserInfo.IsIE && this.Document.hasFocus() )
+ {
+ // In IE it can happen that the document is in theory focused but the active element is outside it
+ this.Document.body.setActive() ;
return ;
+ }
if ( FCKBrowserInfo.IsSafari )
this.IFrame.focus() ;
else
{
this.Window.focus() ;
+
+ // In IE it can happen that the document is in theory focused but the active element is outside it
+ if ( FCKBrowserInfo.IsIE )
+ this.Document.body.setActive() ;
}
}
else
Modified: trunk/fckeditor/editor/_source/classes/fckenterkey.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckenterkey.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckenterkey.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -29,7 +29,7 @@
* @shiftEnterMode : the behavior for the <Shift>+<Enter> keystroke.
* May be "p", "div", "br". Defaults to "br".
*/
-var FCKEnterKey = function( targetWindow, enterMode, shiftEnterMode )
+var FCKEnterKey = function( targetWindow, enterMode, shiftEnterMode, tabSpaces )
{
this.Window = targetWindow ;
this.EnterMode = enterMode || 'p' ;
@@ -43,10 +43,18 @@
oKeystrokeHandler.SetKeystrokes( [
[ 13 , 'Enter' ],
[ SHIFT + 13, 'ShiftEnter' ],
+ [ 9 , 'Tab' ],
[ 8 , 'Backspace' ],
[ 46 , 'Delete' ]
] ) ;
+ if ( tabSpaces > 0 )
+ {
+ this.TabText = '' ;
+ while ( tabSpaces-- > 0 )
+ this.TabText += '\xa0' ;
+ }
+
oKeystrokeHandler.AttachToElement( targetWindow.document ) ;
}
@@ -76,6 +84,9 @@
case 'Delete' :
return oEnterKey.DoDelete() ;
+ break ;
+ case 'Tab' :
+ return oEnterKey.DoTab() ;
}
/* @Packager.RemoveLine
}
@@ -94,6 +105,9 @@
*/
FCKEnterKey.prototype.DoEnter = function( mode, hasShift )
{
+ // Save an undo snapshot before doing anything
+ FCKUndo.SaveUndoStep() ;
+
this._HasShift = ( hasShift === true ) ;
var sMode = mode || this.EnterMode ;
@@ -124,7 +138,22 @@
oRange.MoveToSelection() ;
if ( !oRange.CheckIsCollapsed() )
+ {
+ // Bug #327, Backspace with an img selection would activate the default action in IE.
+ // Let's override that with our logic here.
+ if ( FCKBrowserInfo.IsIE && this.Window.document.selection.type.toLowerCase() == "control" )
+ {
+ var controls = this.Window.document.selection.createRange() ;
+ for ( var i = controls.length - 1 ; i >= 0 ; i-- )
+ {
+ var el = controls.item( i ) ;
+ el.parentNode.removeChild( el ) ;
+ }
+ return true ;
+ }
+
return false ;
+ }
var oStartBlock = oRange.StartBlock ;
var oEndBlock = oRange.EndBlock ;
@@ -256,6 +285,10 @@
*/
FCKEnterKey.prototype.DoDelete = function()
{
+ // Save an undo snapshot before doing anything
+ // This is to conform with the behavior seen in MS Word
+ FCKUndo.SaveUndoStep() ;
+
// The <Delete> has the same effect as the <Backspace>, so we have the same
// results if we just move to the next block and apply the same <Backspace> logic.
@@ -279,6 +312,40 @@
return bCustom ;
}
+/*
+ * Executes the <Tab> key behavior.
+ */
+FCKEnterKey.prototype.DoTab = function()
+{
+ var oRange = new FCKDomRange( this.Window );
+ oRange.MoveToSelection() ;
+
+ // If the user pressed <tab> inside a table, we should give him the default behavior ( moving between cells )
+ // instead of giving him more non-breaking spaces. (Bug #973)
+ var node = oRange._Range.startContainer ;
+ while ( node )
+ {
+ if ( node.nodeType == 1 )
+ {
+ var tagName = node.tagName.toLowerCase() ;
+ if ( tagName == "tr" || tagName == "td" || tagName == "th" || tagName == "tbody" || tagName == "table" )
+ return false ;
+ else
+ break ;
+ }
+ node = node.parentNode ;
+ }
+
+ if ( this.TabText )
+ {
+ oRange.DeleteContents() ;
+ oRange.InsertNode( this.Window.document.createTextNode( this.TabText ) ) ;
+ oRange.Collapse( false ) ;
+ oRange.Select() ;
+ }
+ return true ;
+}
+
FCKEnterKey.prototype._ExecuteEnterBlock = function( blockTag, range )
{
// Get the current selection.
@@ -338,7 +405,10 @@
else
eNewBlock = this.Window.document.createElement( blockTag ) ;
- if ( FCKBrowserInfo.IsGeckoLike )
+ // Opera needs some text (even empty) to correctly position the caret (#214).
+ if ( FCKBrowserInfo.IsOpera )
+ eNewBlock.appendChild( this.Window.document.createTextNode( '' ) ) ;
+ else if ( FCKBrowserInfo.IsGeckoLike )
eNewBlock.innerHTML = GECKO_BOGUS ;
oRange.InsertNode( eNewBlock ) ;
@@ -354,7 +424,7 @@
oRange.MoveToElementEditStart( bIsStartOfBlock ? eNextBlock : eNewBlock ) ;
- if ( FCKBrowserInfo.IsGecko )
+ if ( FCKBrowserInfo.IsGeckoLike )
eNewBlock.scrollIntoView( false ) ;
}
@@ -415,7 +485,7 @@
FCKDomTools.InsertAfterNode( eBr, this.Window.document.createTextNode( '' ) ) ;
// If we are at the end of a block, we must be sure the bogus node is available in that block.
- if ( bIsEndOfBlock && FCKBrowserInfo.IsGecko )
+ if ( bIsEndOfBlock && FCKBrowserInfo.IsGeckoLike )
FCKTools.AppendBogusBr( eBr.parentNode ) ;
if ( FCKBrowserInfo.IsIE )
@@ -456,4 +526,4 @@
range.MoveToBookmark( oBookmark ) ;
range.Select() ;
-}
\ No newline at end of file
+}
Modified: trunk/fckeditor/editor/_source/classes/fckevents.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckevents.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckevents.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -46,7 +46,20 @@
if ( oCalls )
{
for ( var i = 0 ; i < oCalls.length ; i++ )
- bReturnValue = ( oCalls[ i ]( this.Owner, params ) && bReturnValue ) ;
+ {
+ try
+ {
+ bReturnValue = ( oCalls[ i ]( this.Owner, params ) && bReturnValue ) ;
+ }
+ catch(e)
+ {
+ // Ignore the following error. It may happen if pointing to a
+ // script not anymore available (#934):
+ // -2146823277 = Can't execute code from a freed script
+ if ( e.number != -2146823277 )
+ throw e ;
+ }
+ }
}
return bReturnValue ;
Modified: trunk/fckeditor/editor/_source/classes/fckicon.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckicon.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckicon.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -74,7 +74,7 @@
eIcon = document.createElement( 'IMG' ) ;
eIcon.src = FCK_SPACER_PATH ;
eIcon.style.backgroundPosition = '0px ' + sPos ;
- eIcon.style.backgroundImage = 'url(' + this.Path + ')' ;
+ eIcon.style.backgroundImage = 'url("' + this.Path + '")' ;
}
}
else // It is using a single icon image.
Modified: trunk/fckeditor/editor/_source/classes/fckiecleanup.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckiecleanup.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckiecleanup.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -43,7 +43,7 @@
function FCKIECleanup_Cleanup()
{
- if ( !this._FCKCleanupObj )
+ if ( !this._FCKCleanupObj || !window.FCKUnloadFlag )
return ;
var aItems = this._FCKCleanupObj.Items ;
@@ -65,4 +65,4 @@
if ( CollectGarbage )
CollectGarbage() ;
-}
\ No newline at end of file
+}
Modified: trunk/fckeditor/editor/_source/classes/fckkeystrokehandler.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckkeystrokehandler.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckkeystrokehandler.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -133,4 +133,4 @@
}
return true ;
-}
\ No newline at end of file
+}
Modified: trunk/fckeditor/editor/_source/classes/fckpanel.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckpanel.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckpanel.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -52,7 +52,21 @@
oIFrame.width = oIFrame.height = 0 ;
if ( this._Window == window.parent && window.frameElement )
+ {
+ var scrollPos = null ;
+ if ( FCKBrowserInfo.IsGecko && FCK && FCK.EditorDocument )
+ scrollPos = [ FCK.EditorDocument.body.scrollLeft, FCK.EditorDocument.body.scrollTop ] ;
window.frameElement.parentNode.insertBefore( oIFrame, window.frameElement ) ;
+ if ( scrollPos )
+ {
+ var restoreFunc = function()
+ {
+ FCK.EditorDocument.body.scrollLeft = scrollPos[0] ;
+ FCK.EditorDocument.body.scrollTop = scrollPos[1] ;
+ }
+ setTimeout( restoreFunc, 500 ) ;
+ }
+ }
else
this._Window.document.body.appendChild( oIFrame ) ;
@@ -60,9 +74,14 @@
oDocument = this.Document = oIFrameWindow.document ;
+ // Workaround for Safari 12256. Ticket #63
+ var sBase = '' ;
+ if ( FCKBrowserInfo.IsSafari )
+ sBase = '<base href="' + window.document.location + '">' ;
+
// Initialize the IFRAME document body.
oDocument.open() ;
- oDocument.write( '<html><head></head><body style="margin:0px;padding:0px;"><\/body><\/html>' ) ;
+ oDocument.write( '<html><head>' + sBase + '<\/head><body style="margin:0px;padding:0px;"><\/body><\/html>' ) ;
oDocument.close() ;
FCKTools.AddEventListenerEx( oIFrameWindow, 'focus', FCKPanel_Window_OnFocus, this ) ;
@@ -156,7 +175,10 @@
// setting the _IFrame size (which returns "0"), and then after that,
// to return the correct width. Remove the first step and it will not
// work when the editor is in RTL.
- iMainWidth = this.MainNode.offsetWidth ;
+ //
+ // The "|| this.MainNode.firstChild.offsetWidth" part has been added
+ // for Opera compatibility (see #570).
+ iMainWidth = this.MainNode.offsetWidth || this.MainNode.firstChild.offsetWidth ;
var oPos = FCKTools.GetElementPosition(
relElement.nodeType == 9 ?
@@ -302,4 +324,4 @@
this._Window = null ;
this.Document = null ;
this.MainNode = null ;
-}
\ No newline at end of file
+}
Modified: trunk/fckeditor/editor/_source/classes/fckspecialcombo.js
===================================================================
--- trunk/fckeditor/editor/_source/classes/fckspecialcombo.js 2007-09-21 09:35:20 UTC (rev 562)
+++ trunk/fckeditor/editor/_source/classes/fckspecialcombo.js 2007-09-21 09:53:52 UTC (rev 563)
@@ -1,363 +1,364 @@
-/*
- * FCKeditor - The text editor for Internet - http://www.fckeditor.net
- * Copyright (C) 2003-2007 Frederico Caldeira Knabben
- *
- * == BEGIN LICENSE ==
- *
- * Licensed under the terms of any of the following licenses at your
- * choice:
- *
- * - GNU General Public License Version 2 or later (the "GPL")
- * http://www.gnu.org/licenses/gpl.html
- *
- * - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
- * http://www.gnu.org/licenses/lgpl.html
- *
- * - Mozilla Public License Version 1.1 or later (the "MPL")
- * http://www.mozilla.org/MPL/MPL-1.1.html
- *
- * == END LICENSE ==
- *
- * FCKSpecialCombo Class: represents a special combo.
- */
-
-var FCKSpecialCombo = function( caption, fieldWidth, panelWidth, panelMaxHeight, parentWindow )
-{
- // Default properties values.
- this.FieldWidth = fieldWidth || 100 ;
- this.PanelWidth = panelWidth || 150 ;
- this.PanelMaxHeight = panelMaxHeight || 150 ;
- this.Label = ' ' ;
- this.Caption = caption ;
- this.Tooltip = caption ;
- this.Style = FCK_TOOLBARITEM_ICONTEXT ;
-
- this.Enabled = true ;
-
- this.Items = new Object() ;
-
- this._Panel = new FCKPanel( parentWindow || window ) ;
- this._Panel.AppendStyleSheet( FCKConfig.SkinPath + 'fck_editor.css' ) ;
- this._PanelBox = this._Panel.MainNode.appendChild( this._Panel.Document.createElement( 'DIV' ) ) ;
- this._PanelBox.className = 'SC_Panel' ;
- this._PanelBox.style.width = this.PanelWidth + 'px' ;
-
- this._PanelBox.innerHTML = '<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>' ;
-
- this._ItemsHolderEl = this._PanelBox.getElementsByTagName('TD')[0] ;
-
- if ( FCK.IECleanup )
- FCK.IECleanup.AddItem( this, FCKSpecialCombo_Cleanup ) ;
-
-// this._Panel.StyleSheet = FCKConfig.SkinPath + 'fck_contextmenu.css' ;
-// this._Panel.Create() ;
-// this._Panel.PanelDiv.className += ' SC_Panel' ;
-// this._Panel.PanelDiv.innerHTML = '<table cellpadding="0" cellspacing="0" width="100%" style="TABLE-LAYOUT: fixed"><tr><td nowrap></td></tr></table>' ;
-// this._ItemsHolderEl = this._Panel.PanelDiv.getElementsByTagName('TD')[0] ;
-}
-
-function FCKSpecialCombo_ItemOnMouseOver()
-{
- this.className += ' SC_ItemOver' ;
-}
-
-function FCKSpecialCombo_ItemOnMouseOut()
-{
- this.className = this.originalClass ;
-}
-
-function FCKSpecialCombo_ItemOnClick()
-{
- this.className = this.originalClass ;
-
- this.FCKSpecialCombo._Panel.Hide() ;
-
- this.FCKSpecialCombo.SetLabel( this.FCKItemLabel ) ;
-
- if ( typeof( this.FCKSpecialCombo.OnSelect ) == 'function' )
- this.FCKSpecialCombo.OnSelect( this.FCKItemID, this ) ;
-}
-
-FCKSpecialCombo.prototype.AddItem = function( id, html, label, bgColor )
-{
- // <div class="SC_Item" onmouseover="this.className='SC_Item SC_ItemOver';" onmouseout="this.className='SC_Item';"><b>Bold 1</b></div>
- var oDiv = this._ItemsHolderEl.appendChild( this._Panel.Document.createElement( 'DIV' ) ) ;
- oDiv.className = oDiv.originalClass = 'SC_Item' ;
- oDiv.innerHTML = html ;
- oDiv.FCKItemID = id ;
- oDiv.FCKItemLabel = la...
[truncated message content] |