ndieschburg 15 years ago
parent
commit
4efa05e028
100 changed files with 6455 additions and 1515 deletions
  1. 19 8
      documentation/changelog.html
  2. 2 1
      main/admin/add_by_ajax_sub_language.inc.php
  3. 12 33
      main/admin/add_courses_to_session.php
  4. 4 24
      main/admin/add_users_to_session.php
  5. 5 4
      main/admin/admin.class.php
  6. 2 2
      main/admin/course_user_list.php
  7. 2 2
      main/admin/languages.php
  8. 26 17
      main/admin/new_sub_language.php
  9. 8 5
      main/admin/register_sub_language.php
  10. 4 3
      main/auth/inscription.php
  11. 466 466
      main/auth/openid/login.php
  12. 6 30
      main/coursecopy/classes/CourseBuilder.class.php
  13. 4 2
      main/coursecopy/classes/CourseRestorer.class.php
  14. 4 1
      main/css/blue_lagoon/jquery.tabs.css
  15. 13 8
      main/css/cosmic_campus/default.css
  16. 10 8
      main/css/delicious_bordeaux/default.css
  17. 0 8
      main/css/dokeos_blue/default.css
  18. 11 8
      main/css/dokeos_classic/default.css
  19. 11 8
      main/css/dokeos_classic_2D/default.css
  20. 11 7
      main/css/empire_green/default.css
  21. 11 8
      main/css/fruity_orange/default.css
  22. 12 7
      main/css/medical/default.css
  23. 11 7
      main/css/public_admin/default.css
  24. 11 7
      main/css/royal_purple/default.css
  25. 13 12
      main/css/silver_line/default.css
  26. 11 7
      main/css/sober_brown/default.css
  27. 11 7
      main/css/steel_grey/default.css
  28. 11 7
      main/css/tasty_olive/default.css
  29. 14 19
      main/document/slideshowoptions.php
  30. 57 57
      main/dropbox/dropbox_functions.inc.php
  31. 2 8
      main/exercice/adminhp.php
  32. 8 22
      main/exercice/exercice.php
  33. 1 1
      main/exercice/exercise_result.class.php
  34. 30 39
      main/exercice/exercise_submit_modal.php
  35. 12 20
      main/exercice/hotpotatoes.lib.php
  36. 1 1
      main/exercice/showinframes.php
  37. 1 1
      main/exercice/testheaderpage.php
  38. 22 16
      main/forum/forumfunction.inc.php
  39. 1 1
      main/gradebook/gradebook_result.class.php
  40. BIN
      main/img/wiki/assignment.gif
  41. BIN
      main/img/wiki/task.gif
  42. BIN
      main/img/wiki/works.gif
  43. 11 6
      main/inc/global.inc.php
  44. 1 0
      main/inc/lib/add_course.lib.inc.php
  45. 3453 0
      main/inc/lib/asciimath/ASCIIMathML.js
  46. 363 0
      main/inc/lib/asciimath/asciimath.html
  47. 118 0
      main/inc/lib/asciimath/asciimathcalculator.html
  48. 227 0
      main/inc/lib/asciimath/asciimathchanges.txt
  49. 117 0
      main/inc/lib/asciimath/asciimathdemo.html
  50. 76 0
      main/inc/lib/asciimath/asciimathextend.html
  51. 38 0
      main/inc/lib/asciimath/asciimathsample.html
  52. 506 0
      main/inc/lib/asciimath/asciimathsyntax.html
  53. 8 0
      main/inc/lib/asciimath/d.svg
  54. 44 0
      main/inc/lib/asciimath/filter.php
  55. 8 0
      main/inc/lib/asciimath/index.html
  56. 28 0
      main/inc/lib/asciimath/javascript.php
  57. 37 0
      main/inc/lib/asciimath/readme.txt
  58. 3 2
      main/inc/lib/blog.lib.php
  59. 29 4
      main/inc/lib/course.lib.php
  60. 21 38
      main/inc/lib/events.lib.inc.php
  61. 2 2
      main/inc/lib/fckeditor/editor/_source/commandclasses/fck_othercommands.js
  62. 4 4
      main/inc/lib/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js
  63. 178 178
      main/inc/lib/fckeditor/editor/_source/fckeditorapi.js
  64. 32 0
      main/inc/lib/fckeditor/editor/_source/internals/fck.js
  65. 10 0
      main/inc/lib/fckeditor/editor/_source/internals/fck_gecko.js
  66. 14 4
      main/inc/lib/fckeditor/editor/_source/internals/fck_ie.js
  67. 1 1
      main/inc/lib/fckeditor/editor/_source/internals/fckdialog.js
  68. 38 10
      main/inc/lib/fckeditor/editor/_source/internals/fckdomtools.js
  69. 17 0
      main/inc/lib/fckeditor/editor/_source/internals/fckxhtml.js
  70. 36 0
      main/inc/lib/fckeditor/editor/_source/internals/fckxhtml_ie.js
  71. 1 1
      main/inc/lib/fckeditor/editor/dialog/common/fck_dialog_common.js
  72. 6 1
      main/inc/lib/fckeditor/editor/dialog/fck_about.html
  73. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_anchor.html
  74. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_button.html
  75. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_checkbox.html
  76. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_colorselector.html
  77. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_div.html
  78. 22 17
      main/inc/lib/fckeditor/editor/dialog/fck_docprops.html
  79. 1 1
      main/inc/lib/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html
  80. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_flash.html
  81. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_form.html
  82. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_hiddenfield.html
  83. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_image.html
  84. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_link.html
  85. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_listprop.html
  86. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_paste.html
  87. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_radiobutton.html
  88. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_replace.html
  89. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_select.html
  90. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_smiley.html
  91. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_source.html
  92. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_specialchar.html
  93. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_spellerpages.html
  94. 0 148
      main/inc/lib/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm
  95. 0 181
      main/inc/lib/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl
  96. 27 22
      main/inc/lib/fckeditor/editor/dialog/fck_table.html
  97. 8 3
      main/inc/lib/fckeditor/editor/dialog/fck_tablecell.html
  98. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_template.html
  99. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_textarea.html
  100. 5 0
      main/inc/lib/fckeditor/editor/dialog/fck_textfield.html

+ 19 - 8
documentation/changelog.html

@@ -33,16 +33,27 @@
   <li>An internationalization option has been added for improving sorting in arbitrary language. When the <a href="http://php.net/manual/en/book.intl.php" target="_blank">intl</a> php-extension has been installed, various sorting routines exploit it for better sorting. Rationale: The PHP5 run-time environment does not provide native and reliable way of sorting UTF-8 strings. (FS#306)</li>
   <li>The installation sript: The page about system requilements has been updated. Also, at the very beginning, a check has been added whether the <a href="http://php.net/manual/en/book.mbstring.php" target="_blank">mbstring</a> php-extension is installed - see <a href="http://dokeos.com/forum/viewtopic.php?t=29548" target="_blank">the related forum topic</a>. (FS#306)</li>
   <li>A new php-based configuration for the online editor has been implemented, see <i>dokeos/main/inc/lib/fckeditor/myconfig.php</i>. Also, toolbar definitions have been split in separate php-files within the directory <i>dokeos/main/inc/lib/fckeditor/toolbars/</i> . Customization of the editor is more convenient and flexible now. (FS#2867)</li>
-  <li>The online editor: A upgrade from FCKEditor 2.6.4 to <b>FCKEditor 2.6.4.1</b> has been implemented. (FS#4383)</li>
-  <li>The online editor: Several known bug-fixes from FCKEditor 2.6.5 SVN have been implemented, tickets <a href="http://dev.fckeditor.net/ticket/2821" target="_blank">#2821</a>, <a href="http://dev.fckeditor.net/ticket/2856" target="_blank">#2856</a>, <a href="http://dev.fckeditor.net/ticket/2915" target="_blank">#2915</a>, <a href="http://dev.fckeditor.net/ticket/3120" target="_blank">#3120</a>, <a href="http://dev.fckeditor.net/ticket/3181" target="_blank">#3181</a>, <a href="http://dev.fckeditor.net/ticket/3429" target="_blank">#3429</a>, <a href="http://dev.fckeditor.net/ticket/3439" target="_blank">#3439</a>, <a href="http://dev.fckeditor.net/ticket/3880" target="_blank">#3880</a>. (FS#2867)</li>
-  <li>The online editor: The simple file manager, the advanced file manager and the image manager have been integrated by default with the editor's dialog system. Thus, they work faster and in a more secure way. (FS#2867)</li>
-  <li>The online editor: Blocking copy/paste for trainees has been added. The feature is configurable through editing the toolbar definition files within the directory <i>dokeos/main/inc/lib/fckeditor/toolbars/</i> . (FS#2867)</li>
-  <li>The online editor: Preview tabs have been added to the dialogs for inserting video, flv-video, and YouTube video. (FS#2867)</li>
-  <li>The online editor: The <b>audio</b> plugin has been activated by default as an implementation of the "Insert audio / Audio properties" dialog. This new plugin is intended to replace the "MP3" plugin. (FS#2867)</li>
-  <li>The online editor: Configuration of the <b>mimetex</b> plugin has been reworked to gain simplicity. The procedure for configuration has been updated, see <a href="http://www.dokeos.com/forum/viewtopic.php?t=29594" target="_blank">the related forum topic</a>. (FS#2867)</li>
-  <li>The online editor: The toolbar icons have been upgraded to those from CKEditor 3.0. (FS#2867)</li>
+  <li>Online editor: A upgrade from FCKEditor 2.6.4 to <b>FCKEditor 2.6.4.1</b> has been implemented. (FS#4383)</li>
+  <li>Online editor: Several known bug-fixes from FCKEditor 2.6.5 SVN have been implemented, tickets <a href="http://dev.fckeditor.net/ticket/1537" target="_blank">#1537</a>, <a href="http://dev.fckeditor.net/ticket/2156" target="_blank">#2156</a>, <a href="http://dev.fckeditor.net/ticket/2689" target="_blank">#2689</a>, <a href="http://dev.fckeditor.net/ticket/2821" target="_blank">#2821</a>, <a href="http://dev.fckeditor.net/ticket/2856" target="_blank">#2856</a>, <a href="http://dev.fckeditor.net/ticket/2874" target="_blank">#2874</a>, <a href="http://dev.fckeditor.net/ticket/2915" target="_blank">#2915</a>, <a href="http://dev.fckeditor.net/ticket/3120" target="_blank">#3120</a>, <a href="http://dev.fckeditor.net/ticket/3181" target="_blank">#3181</a>, <a href="http://dev.fckeditor.net/ticket/3427" target="_blank">#3427</a>, <a href="http://dev.fckeditor.net/ticket/3429" target="_blank">#3429</a>, <a href="http://dev.fckeditor.net/ticket/3439" target="_blank">#3439</a>, <a href="http://dev.fckeditor.net/ticket/3446" target="_blank">#3446</a>, <a href="http://dev.fckeditor.net/ticket/3481" target="_blank">#3481</a>, <a href="http://dev.fckeditor.net/ticket/3677" target="_blank">#3677</a>, <a href="http://dev.fckeditor.net/ticket/3818" target="_blank">#3818</a>, <a href="http://dev.fckeditor.net/ticket/3880" target="_blank">#3880</a>, <a href="http://dev.fckeditor.net/ticket/3925" target="_blank">#3925</a>. (FS#2867)</li>
+  <li>Online editor: The simple file manager, the advanced file manager and the image manager have been integrated by default with the editor's dialog system. Thus, they work faster and in a more secure way. (FS#2867)</li>
+  <li>Online editor: Blocking copy/paste for trainees has been added. The feature is configurable through editing the toolbar definition files within the directory <i>dokeos/main/inc/lib/fckeditor/toolbars/</i> . (FS#2867)</li>
+  <li>Online editor: Preview tabs have been added to the dialogs for inserting video, flv-video, and YouTube video. (FS#2867)</li>
+  <li>Online editor: The <b>audio</b> plugin has been activated by default as an implementation of the "Insert audio / Audio properties" dialog. This new plugin is intended to replace the "MP3" plugin. (FS#2867)</li>
+  <li>Online editor: Configuration of the <b>mimetex</b> plugin has been reworked to gain simplicity. The procedure for configuration has been updated, see <a href="http://www.dokeos.com/forum/viewtopic.php?t=29594" target="_blank">the related forum topic</a>. (FS#2867)</li>
+  <li>Online editor: A new <b>asciimath</b> plugin for inserting mathematical formulas has been added. It is based on the <a href="http://mathcs.chapman.edu/~jipsen/mathml/asciimath.html" target="_blank">ASCIIMathML.js</a> library. (FS#2867)</li>
+  <li>Online editor: The toolbar icons have been upgraded to those from CKEditor 3.0. (FS#2867)</li>
   <li>A solution has been implemented for fixing the <a href="http://bugs.adobe.com/jira/browse/FP-529" target="_blank">"__flash__removeCallback" bug</a>, which affects the media player on Internet Explorer browser. (FS#4378 and FS#2867)</li>
   <li>Implement new sub-language feature by which language terms redefinition becomes possible through the admin section (FS#4321)</li>
+  <li>Social: Added possibility to define RSS feeds inside personal page of social network (need to define an 'rssfeeds' extra user text field)</li>
+  <li>Admin: Added courses from sessions inside AJAX popup of courses list in users list (SVN#22398)</li>
+  <li>Admin: Showing full-length course titles in list of courses while adding to sessions(SVN#22399)</li>
+  <li>Admin: Added session name in title of session edition pages(SVN#22400)</li>
+</ul>
+<br />
+<h3>Known issues</h3>
+<ul>
+  <li></li>
+  <li></li>
 </ul>
 <br />
 <h3>Known issues</h3>

+ 2 - 1
main/admin/add_by_ajax_sub_language.inc.php

@@ -12,8 +12,9 @@ $new_language=Security::remove_XSS($_POST['new_language']);
 $language_variable=Security::remove_XSS($_POST['variable_language']);
 $file_language=Security::remove_XSS($_POST['file_language']);
 $id_language=Security::remove_XSS($_POST['id']);
+$sub_language_id=Security::remove_XSS($_POST['sublanguage_id']);
  
-$all_data_of_language=AdminManager::get_all_information_of_sub_language($_POST['id']);
+$all_data_of_language=AdminManager::get_all_information_of_sub_language($id_language,$sub_language_id);
 $dokeos_path_folder=api_get_path('SYS_LANG_PATH').$all_data_of_language['dokeos_folder'].'/'.$file_language;
 $all_file_of_directory=AdminManager::get_all_language_variable_in_file($dokeos_path_folder);
 AdminManager::add_file_in_language_directory ($dokeos_path_folder);

+ 12 - 33
main/admin/add_courses_to_session.php

@@ -1,26 +1,5 @@
-<?php
-/*
-==============================================================================
-	Dokeos - elearning and course management software
-
-	Copyright (c) 2004-2009 Dokeos SPRL
-	Copyright (c) 2003 Ghent University (UGent)
-	Copyright (c) 2001 Universite catholique de Louvain (UCL)
-	Copyright (c) Olivier Brouckaert
-
-	For a full list of contributors, see "credits.txt".
-	The full license can be read in "license.txt".
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	See the GNU General Public License for more details.
-
-	Contact: Dokeos, rue du Corbeau, 108, B-1030 Brussels, Belgium, info@dokeos.com
-==============================================================================
-*/
+<?php //$id: $
+/* For licensing terms, see /dokeos_license.txt */
 /**
 ==============================================================================
 *	@package dokeos.admin
@@ -35,11 +14,11 @@ $language_file='admin';
 $cidReset=true;
 
 // including some necessary dokeos files
-require('../inc/global.inc.php');
+require '../inc/global.inc.php';
 
 // including additonal libraries
-require_once ('../inc/lib/xajax/xajax.inc.php');
-require_once (api_get_path(LIBRARY_PATH).'sessionmanager.lib.php');
+require_once '../inc/lib/xajax/xajax.inc.php';
+require_once api_get_path(LIBRARY_PATH).'sessionmanager.lib.php';
 $xajax = new xajax();
 //$xajax->debugOn();
 $xajax -> registerFunction ('search_courses');
@@ -164,7 +143,7 @@ function search_courses($needle,$type)
 			while($course = Database :: fetch_array($rs)) {	
 				$course_list[] = $course['code'];
 				$course_title=str_replace("'","\'",$course_title);				
-				$return .= '<option value="'.$course['code'].'">'.$course['title'].' ('.$course['visual_code'].')</option>';				
+				$return .= '<option value="'.$course['code'].'" title="'.htmlspecialchars($course['title'].' ('.$course['visual_code'].')',ENT_QUOTES).'">'.$course['title'].' ('.$course['visual_code'].')</option>';				
 			}
 			$return .= '</select>';
 			
@@ -301,8 +280,9 @@ echo '<div class="actions">';
 echo $link_add_type_unique.$link_add_type_multiple;
 echo '</div>';
 
-// the form header 
-echo '<div class="row"><div class="form_header">'.$tool_name.'</div></div>';
+// the form header
+$session_info = SessionManager::fetch($id_session);
+echo '<div class="row"><div class="form_header">'.$tool_name.' ('.$session_info['name'].')</div></div>';
 
 
 /*$sql = 'SELECT COUNT(1) FROM '.$tbl_course;
@@ -436,7 +416,7 @@ else
 	foreach($nosessionCourses as $enreg)
 	{
 		?>
-		<option value="<?php echo $enreg['code']; ?>" <?php if(in_array($enreg['code'],$CourseList)) echo 'selected="selected"'; ?>><?php echo $enreg['title'].' ('.$enreg['visual_code'].')'; ?></option>
+		<option value="<?php echo $enreg['code']; ?>" <?php echo 'title="'.htmlspecialchars($enreg['title'].' ('.$enreg['visual_code'].')',ENT_QUOTES).'"'; if(in_array($enreg['code'],$CourseList)) echo 'selected="selected"'; ?>><?php echo $enreg['title'].' ('.$enreg['visual_code'].')'; ?></option>
 		<?php
 	}
 	?>  </select></div> <?php
@@ -447,8 +427,7 @@ unset($nosessionCourses);
   </select></td>
   <td width="10%" valign="middle" align="center">
   <?php
-  if($ajax_search)
-  {
+  if ($ajax_search) {
   ?>
   	<input type="button" onclick="remove_item(document.getElementById('destination'))" value="<<" />
   <?php
@@ -480,7 +459,7 @@ unset($nosessionCourses);
 foreach($sessionCourses as $enreg)
 {	
 ?>	
-	<option value="<?php echo $enreg['code']; ?>"><?php echo $enreg['title'].' ('.$enreg['visual_code'].')'; ?></option>
+	<option value="<?php echo $enreg['code']; ?>" title="<?php echo htmlspecialchars($enreg['title'].' ('.$enreg['visual_code'].')',ENT_QUOTES); ?>"><?php echo $enreg['title'].' ('.$enreg['visual_code'].')'; ?></option>
 
 <?php 
 }

+ 4 - 24
main/admin/add_users_to_session.php

@@ -1,26 +1,5 @@
-<?php
-/*
-==============================================================================
-	Dokeos - elearning and course management software
-
-	Copyright (c) 2004-2009 Dokeos SPRL
-	Copyright (c) 2003 Ghent University (UGent)
-	Copyright (c) 2001 Universite catholique de Louvain (UCL)
-	Copyright (c) Olivier Brouckaert
-
-	For a full list of contributors, see "credits.txt".
-	The full license can be read in "license.txt".
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	See the GNU General Public License for more details.
-
-	Contact: Dokeos, rue du Corbeau, 108, B-1030 Brussels, Belgium, info@dokeos.com
-==============================================================================
-*/
+<?php //$id: $
+/* For licensing terms, see /dokeos_license.txt */
 /**
 ==============================================================================
 *	@package dokeos.admin
@@ -275,8 +254,9 @@ if($_POST['form_sent']) {
 	}
 }
 
+$session_info = SessionManager::fetch($id_session);
 Display::display_header($tool_name);
-api_display_tool_title($tool_name);
+api_display_tool_title($tool_name.' ('.$session_info['name'].')');
 
 $nosessionUsersList = $sessionUsersList = array();
 /*$sql = 'SELECT COUNT(1) FROM '.$tbl_user;

+ 5 - 4
main/admin/admin.class.php

@@ -39,11 +39,12 @@ class AdminManager {
     /**
      * Get all information of sub-language
      * @param Integer The parent id(Language father id)
+     * @param Integer The sub language id
      * @return Array All information about sub-language
      */
-	public static function get_all_information_of_sub_language ($parent_id) {
+	public static function get_all_information_of_sub_language ($parent_id,$sub_language_id) {
 		$tbl_admin_languages 	= Database :: get_main_table(TABLE_MAIN_LANGUAGE);	
-		$sql='SELECT * FROM '.$tbl_admin_languages.' WHERE parent_id="'.Database::escape_string($parent_id).'"';
+		$sql='SELECT * FROM '.$tbl_admin_languages.' WHERE parent_id="'.Database::escape_string($parent_id).'" AND id="'.Database::escape_string($sub_language_id).'"';
 		$rs=Database::query($sql,__FILE__,__LINE__);
 		$all_information=array();
 		while ($row=Database::fetch_array($rs,'ASSOC')) {
@@ -123,9 +124,9 @@ class AdminManager {
 	 * @param Integer The parent id
 	 * @return void()
 	 */   
-   public static function removed_sub_language ($parent_id) {
+   public static function removed_sub_language ($parent_id,$sub_language_id) {
    		$tbl_admin_languages 	= Database :: get_main_table(TABLE_MAIN_LANGUAGE);		
-		$sql='DELETE FROM '.$tbl_admin_languages.' WHERE parent_id="'.Database::escape_string($parent_id).'"';
+		$sql='DELETE FROM '.$tbl_admin_languages.' WHERE parent_id="'.Database::escape_string($parent_id).'" AND id="'.Database::escape_string($sub_language_id).'" ';
     	$rs=Database::query($sql,__FILE__,__LINE__);
    }
    	/**

+ 2 - 2
main/admin/course_user_list.php

@@ -5,7 +5,7 @@ require_once '../inc/lib/course.lib.php';
 $user_id=intval($_POST['user_id']);
 $list_course_all_info=array();
 $list_course=array();
-$list_course_all_info=CourseManager::get_courses_list_by_user_id($user_id);
+$list_course_all_info=CourseManager::get_courses_list_by_user_id($user_id,true);
 for ($i=0;$i<count($list_course_all_info);$i++) {
 	$list_course[]=$list_course_all_info[$i]['title'];
 }
@@ -25,4 +25,4 @@ if (count($list_course)==0) {
         <td><?php echo api_convert_encoding($list_course[$k],'UTF-8',$charset);?></td>
     </tr>
 <?php }?>	
-</table>
+</table>

+ 2 - 2
main/admin/languages.php

@@ -264,8 +264,8 @@ while ($row = Database::fetch_array($result_select)) {
 		} else {
 				$allow_use_sub_language='';
 				$all_information_of_sub_language=AdminManager::get_all_information_of_language($row['id']);
-				$allow_add_term_sub_language = "&nbsp;<a href='register_sub_language.php?action=registersublanguage&id=".$all_information_of_sub_language['parent_id']."'>".Display::return_icon('2rightarrow.gif', get_lang('AddWordForTheSubLanguage'),array('width'=>'22','height'=>'22'))."</a>";									
-				$allow_delete_sub_language = "&nbsp;<a href='new_sub_language.php?action=deletesublanguage&id=".$all_information_of_sub_language['parent_id']."'>".Display::return_icon('delete_data.gif', get_lang('DeleteSubLanguage'),array('width'=>'22','height'=>'22'))."</a>";		
+				$allow_add_term_sub_language = "&nbsp;<a href='register_sub_language.php?action=registersublanguage&id=".Security::remove_XSS($all_information_of_sub_language['parent_id'])."&sub_language_id=".Security::remove_XSS($row['id'])."'>".Display::return_icon('2rightarrow.gif', get_lang('AddWordForTheSubLanguage'),array('width'=>'22','height'=>'22'))."</a>";									
+				$allow_delete_sub_language = "&nbsp;<a href='new_sub_language.php?action=deletesublanguage&id=".Security::remove_XSS($all_information_of_sub_language['parent_id'])."&sub_language_id=".Security::remove_XSS($row['id'])."'>".Display::return_icon('delete_data.gif', get_lang('DeleteSubLanguage'),array('width'=>'22','height'=>'22'))."</a>";		
 		}
 		
 	} else {

+ 26 - 17
main/admin/new_sub_language.php

@@ -109,15 +109,10 @@ function ckeck_if_is_parent_of_sub_language ($parent_id) {
 /**
  * Get all information of sub-language
  */
-function allow_get_all_information_of_sub_language ($parent_id) {
-	return AdminManager::get_all_information_of_sub_language($parent_id); 
-}
-/**
- * Delete sub-language
- */
-function removed_sub_language ($parent_id) {
-	AdminManager::removed_sub_language($parent_id);
+function allow_get_all_information_of_sub_language ($parent_id,$sub_language_id) {
+	return AdminManager::get_all_information_of_sub_language($parent_id,$sub_language_id); 
 }
+
 /**
  * Add directory for sub-language 
  */
@@ -153,7 +148,19 @@ function remove_directory_of_sub_language ($path) {
 }
 /*end declare functions*/
 
-//add register
+//add data
+
+if (isset($_GET['sub_language_id']) && $_GET['sub_language_id']==strval(intval($_GET['sub_language_id']))) {
+	$language_name=get_name_of_language_by_id($_GET['sub_language_id']);
+		if (check_if_exist_language_by_id ($_GET['sub_language_id'])===true) {
+			$sub_language_id=$_GET['sub_language_id'];
+			$sub_language_id_exist=true;
+		} else {
+			$sub_language_id_exist=false;
+		}
+		
+}
+
 if (isset($_GET['id']) && $_GET['id']==strval(intval($_GET['id']))) {
 	$language_name=get_name_of_language_by_id($_GET['id']);
 		if (check_if_exist_language_by_id ($_GET['id'])===true) {
@@ -170,9 +177,9 @@ if (isset($_GET['id']) && $_GET['id']==strval(intval($_GET['id']))) {
 
 //removed and register
 
-if (isset($_GET['id']) && $_GET['id']==strval(intval($_GET['id']))) {
-	if (check_if_exist_language_by_id($_GET['id'])===true) {
-	 	$get_all_information=allow_get_all_information_of_sub_language ($_GET['id']);
+if ((isset($_GET['id']) && $_GET['id']==strval(intval($_GET['id']))) && (isset($_GET['sub_language_id']) && $_GET['sub_language_id']==strval(intval($_GET['sub_language_id'])))) {
+	if (check_if_exist_language_by_id($_GET['id'])===true && check_if_exist_language_by_id($_GET['sub_language_id'])===true) {
+	 	$get_all_information=allow_get_all_information_of_sub_language ($_GET['id'],$_GET['sub_language_id']);
 		$original_name=$get_all_information['original_name'];
 		$english_name=$get_all_information['english_name'];
 		$isocode=$get_all_information['isocode'];
@@ -243,15 +250,17 @@ if (isset($_POST['SubmitAddDeleteLanguage'])) {
 	if (is_dir($path)) {
 		$rs=remove_directory_of_sub_language($path);
 		if ($rs===true) {
-			removed_sub_language($parent_id);
+			AdminManager::removed_sub_language($parent_id,$sub_language_id);
+			Display::display_confirmation_message(get_lang('TheSubLanguageHasBeenRemoved'));
 		}
 		
 	}
 }
-	
-	if (ckeck_if_is_parent_of_sub_language ($parent_id)===false ) {
+     // ckeck_if_is_parent_of_sub_language($parent_id)===false
+	//
+	if (isset($_GET['action']) && $_GET['action']=='definenewsublanguage') {
 		$text=$language_name;
-		$form = new FormValidator('addsublanguage', 'post', 'new_sub_language.php?id='.Security::remove_XSS($_GET['id']));
+		$form = new FormValidator('addsublanguage', 'post', 'new_sub_language.php?id='.Security::remove_XSS($_GET['id']).'&action=definenewsublanguage');
 		$class='add';
 		$form->addElement('header', '', $text);			
 		$form->addElement('text', 'original_name', get_lang('OriginalName'),'class="input_titles"');
@@ -266,7 +275,7 @@ if (isset($_POST['SubmitAddDeleteLanguage'])) {
 	} else {
 		if (isset($_GET['action']) && $_GET['action']=='deletesublanguage') {
 			$text=$language_name;
-			$form = new FormValidator('deletesublanguage', 'post', 'new_sub_language.php?id='.Security::remove_XSS($_GET['id']));
+			$form = new FormValidator('deletesublanguage', 'post', 'new_sub_language.php?id='.Security::remove_XSS($_GET['id']).'&sub_language_id='.Security::remove_XSS($_GET['sub_language_id']));
 			$class='minus';
 			$form->addElement('header', '', $text);
 			$form->addElement('static', '', get_lang('OriginalName'),$original_name);

+ 8 - 5
main/admin/register_sub_language.php

@@ -51,6 +51,7 @@ $htmlHeadXtra[] ='<script type="text/javascript">
 		button_name=button_name.split("_");
 		button_name=button_name[1];
 		is_id=$("#id_hidden_original_file").attr("value");
+		is_sublanguage_id=$("#id_hidden_sublanguage").attr("value");
 		is_variable_language="$"+button_name;
 		is_new_language=$("#txtid_"+button_name).attr("value");
 		if (is_new_language=="undefined") {
@@ -66,7 +67,7 @@ $htmlHeadXtra[] ='<script type="text/javascript">
 				},
 				type: "POST",
 				url: "../admin/add_by_ajax_sub_language.inc.php",
-				data: "new_language="+is_new_language+"&variable_language="+is_variable_language+"&file_language="+is_file_language+"&id="+is_id,
+				data: "new_language="+is_new_language+"&variable_language="+is_variable_language+"&file_language="+is_file_language+"&id="+is_id+"&sublanguage_id="+is_sublanguage_id,
 				success: function(datos) {
 					$("#div_message_information_id").html("<div class=\"confirmation-message\">'.get_lang('TheNewWordHasBeenAdded').'</div>");
 				
@@ -158,8 +159,9 @@ $form->display();
 echo '</div>';*/
 
 $html.='<div style="float:left" class="actions" >';
-$html.='<form style="float:left" id="Loadlanguage" name="Loadlanguage" method="post" action="register_sub_language.php?id='.Security::remove_XSS($_GET['id']).'&original_file='.$request_file.'" >';
+$html.='<form style="float:left" id="Loadlanguage" name="Loadlanguage" method="post" action="register_sub_language.php?id='.Security::remove_XSS($_GET['id']).'&sub_language_id='.Security::remove_XSS($_GET['sub_language_id']).'&original_file='.$request_file.'" >';
 $html.='<input  type="hidden" name="id_hidden_original_file" id="id_hidden_original_file" value="'.Security::remove_XSS($_REQUEST['id']).'" />';
+$html.='<input  type="hidden" name="id_hidden_sublanguage" id="id_hidden_sublanguage" value="'.Security::remove_XSS($_REQUEST['sub_language_id']).'" />';
 $html.='<select id="sl_original_file" name="original_file">';
 //$html.='<option value="0">'.get_lang('SelectAChoice').'</option>';
 foreach ($load_array_in_select as $index_radios_results_enabled=>$value_radios_results_enabled) {
@@ -171,7 +173,7 @@ $html.='</form>';
 $html.='</div>';
 
 $html.='<div style="float:left" class="actions">';
-$html.='<form style="float:left"  id="Searchlanguage" name="Searchlanguage" method="post" action="register_sub_language.php?id='.Security::remove_XSS($_GET['id']).'&original_file='.$request_file.'" >';
+$html.='<form style="float:left"  id="Searchlanguage" name="Searchlanguage" method="post" action="register_sub_language.php?id='.Security::remove_XSS($_GET['id']).'&sub_language_id='.Security::remove_XSS($_GET['sub_language_id']).'&original_file='.$request_file.'" >';
 $html.='&nbsp;'.get_lang('OriginalName').'&nbsp; :&nbsp;';
 $html.='<input name="txt_search_word" type="text" size="30"  id="txt_search_word" value="" />';
 $html.='<button name="SubmitSearchLanguage" class="search" type="submit">'.get_lang('Search').'</button>';
@@ -201,7 +203,8 @@ if (isset($_REQUEST['txt_search_word']) && strlen(trim($_REQUEST['txt_search_wor
 }
 if($search_data===true) { 
 	$parent_id=Security::remove_XSS($_REQUEST['id']);
-	$get_all_info_of_sub_language=AdminManager::get_all_information_of_sub_language ($parent_id);
+	$sub_language_id=Security::remove_XSS($_REQUEST['sub_language_id']);
+	$get_all_info_of_sub_language=AdminManager::get_all_information_of_sub_language ($parent_id,$sub_language_id);
 	$dokeos_path_file=api_get_path('SYS_LANG_PATH').$all_data_of_language['dokeos_folder'].'/'.$request_file;	
 
 	$dokeos_english_path_file=api_get_path('SYS_LANG_PATH').'english/'.$request_file;
@@ -265,7 +268,7 @@ if (isset($_REQUEST['txt_search_word']) && strlen(trim($_REQUEST['txt_search_wor
 	}
 }
 }
-$parameters=array('id'=>Security::remove_XSS($_GET['id']),'original_file'=>$request_file);
+$parameters=array('id'=>Security::remove_XSS($_GET['id']),'original_file'=>$request_file,'sub_language_id'=>Security::remove_XSS($_GET['sub_language_id']));
 if (isset($_REQUEST['txt_search_word']) && strlen($_REQUEST['txt_search_word'])>0) {
 	$parameters['txt_search_word']=Security::remove_XSS($_REQUEST['txt_search_word']);
 }

+ 4 - 3
main/auth/inscription.php

@@ -1,5 +1,5 @@
 <?php
-// $Id: inscription.php 22368 2009-07-24 23:25:57Z iflorespaz $
+// $Id: inscription.php 22567 2009-08-02 23:10:29Z iflorespaz $
 /*
 ==============================================================================
 	Dokeos - elearning and course management software
@@ -317,12 +317,13 @@ if (get_setting('allow_terms_conditions')=='true') {
 	
 	// Version and language //password
 	$form->addElement('hidden', 'legal_accept_type',$term_preview['version'].':'.$term_preview['language_id']);
+	$form->addElement('hidden', 'legal_info',$term_preview['legal_id'].':'.$term_preview['language_id']);	
 	if (isset($_SESSION['info_current_user'][1]) && isset($_SESSION['info_current_user'][2])) {
 		$form->addElement('hidden', 'login',$_SESSION['info_current_user'][1]);
-		$form->addElement('hidden', 'password',$_SESSION['info_current_user'][2]);		
+		$form->addElement('hidden', 'password',$_SESSION['info_current_user'][2]);	
 	}
 	if($term_preview['type'] == 1) {
-		$form->addElement('checkbox', 'legal_accept', null, get_lang('IhaveReadAndAgree').'&nbsp;<a href="inscription.php?legal" target="_blank">'.get_lang('TermsAndConditions').'</a>');		
+		$form->addElement('checkbox', 'legal_accept', null, get_lang('IHaveReadAndAgree').'&nbsp;<a href="inscription.php?legal" target="_blank">'.get_lang('TermsAndConditions').'</a>');		
 		$form->addRule('extra_legal_accept',  get_lang('ThisFieldIsRequired'), 'required');
 	} else {
 		if (!empty($term_preview['content'])) {			

+ 466 - 466
main/auth/openid/login.php

@@ -1,467 +1,467 @@
-<?php
-/**
- * OpenID login method
- * 
- * The OpenID login method relies on authentication servers providing a public
- * URL that can confirm the identity of a person, thus avoiding the spread
- * use of password transmissions over non-secure lines (for Dokeos, it is a
- * good way of avoiding password theft)
- */
-/**
- * Initialisation
- */
-require_once('openid.conf.php');
-require_once('openid.lib.php');
-require_once('xrds.lib.php');
-
-function openid_form() 
-{
-	return '<div class="menusection"><span class="menusectioncaption">'.get_lang('OpenIdAuthentication').'</span><form name="openid_login" method="post"><label for="openid_url">'.get_lang('OpenIDURL').' <a href="main/auth/openid/whatis.php" title="'.get_lang('OpenIDWhatIs').'">'.Display::return_icon('info3.gif').'</a></label><input type="text" id="openid_url" name="openid_url" style="background: url(main/img/openid_small_logo.png) no-repeat; background-color: #fff; background-position: 0 50%; padding-left:18px;" value="http://"></input><input type="submit" name="openid_login" value="'.get_lang('Ok').'" /><br /><br /></form></div>';
-}
-
-/**
- * The initial step of OpenID authentication responsible for the following:
- *  - Perform discovery on the claimed OpenID.
- *  - If possible, create an association with the Provider's endpoint.
- *  - Create the authentication request.
- *  - Perform the appropriate redirect.
- *
- * @param $claimed_id The OpenID to authenticate
- * @param $return_to The endpoint to return to from the OpenID Provider
- */
-function openid_begin($claimed_id, $return_to = '', $form_values = array()) 
-{
-
-  $claimed_id = _openid_normalize($claimed_id);
-
-  $services = openid_discovery($claimed_id);
-  if (count($services) == 0) {
-    echo 'Sorry, that is not a valid OpenID. Please ensure you have spelled your ID correctly.';
-    return;
-  }
-
-  $op_endpoint = $services[0]['uri'];
-  // Store the discovered endpoint in the session (so we don't have to rediscover).
-  $_SESSION['openid_op_endpoint'] = $op_endpoint;
-  // Store the claimed_id in the session (for handling delegation).
-  $_SESSION['openid_claimed_id'] = $claimed_id;
-  // Store the login form values so we can pass them to
-  // user_exteral_login later.
-  $_SESSION['openid_user_login_values'] = $form_values;
-
-  // If bcmath is present, then create an association
-  $assoc_handle = '';
-  if (function_exists('bcadd')) {
-    $assoc_handle = openid_association($op_endpoint);
-  }
-
-  // Now that there is an association created, move on
-  // to request authentication from the IdP
-  $identity = (!empty($services[0]['delegate'])) ? $services[0]['delegate'] : $claimed_id;
-  if (isset($services[0]['types']) && is_array($services[0]['types']) && in_array(OPENID_NS_2_0 .'/server', $services[0]['types'])) {
-    $identity = 'http://openid.net/identifier_select/2.0';
-  }
-  $authn_request = openid_authentication_request($claimed_id, $identity, $return_to, $assoc_handle, $services[0]['version']);
-
-  if ($services[0]['version'] == 2) {
-    openid_redirect($op_endpoint, $authn_request);
-  }
-  else {
-    openid_redirect_http($op_endpoint, $authn_request);
-  }
-}
-
-/**
- * Completes OpenID authentication by validating returned data from the OpenID
- * Provider.
- *
- * @param $response Array of returned from the OpenID provider (typically $_REQUEST).
- *
- * @return $response Response values for further processing with
- *   $response['status'] set to one of 'success', 'failed' or 'cancel'.
- */
-function openid_complete($response) 
-{
-  // Default to failed response
-  $response['status'] = 'failed';
-  if (isset($_SESSION['openid_op_endpoint']) && isset($_SESSION['openid_claimed_id'])) {
-    _openid_fix_post($response);
-    $op_endpoint = $_SESSION['openid_op_endpoint'];
-    $claimed_id = $_SESSION['openid_claimed_id'];
-    unset($_SESSION['openid_op_endpoint']);
-    unset($_SESSION['openid_claimed_id']);
-    if (isset($response['openid.mode'])) {
-      if ($response['openid.mode'] == 'cancel') {
-        $response['status'] = 'cancel';
-      }
-      else {
-        if (openid_verify_assertion($op_endpoint, $response)) {
-          $response['openid.identity'] = $claimed_id;
-          $response['status'] = 'success';
-        }
-      }
-    }
-  }
-  return $response;
-}
-
-/**
- * Perform discovery on a claimed ID to determine the OpenID provider endpoint.
- *
- * @param $claimed_id The OpenID URL to perform discovery on.
- *
- * @return Array of services discovered (including OpenID version, endpoint
- * URI, etc).
- */
-function openid_discovery($claimed_id) {
-
-  $services = array();
-
-  $xrds_url = $claimed_id;
-  if (_openid_is_xri($claimed_id)) {
-    $xrds_url = 'http://xri.net/'. $claimed_id;
-  }
-  $url = @parse_url($xrds_url);
-  if ($url['scheme'] == 'http' || $url['scheme'] == 'https') {
-    // For regular URLs, try Yadis resolution first, then HTML-based discovery
-    $headers = array('Accept' => 'application/xrds+xml');
-    //TODO
-    $result = openid_http_request($xrds_url, $headers);
-
-    if (!isset($result->error)) {
-      if (isset($result->headers['Content-Type']) && preg_match("/application\/xrds\+xml/", $result->headers['Content-Type'])) {
-        // Parse XML document to find URL
-        $services = xrds_parse($result->data);
-      }
-      else {
-        $xrds_url = NULL;
-        if (isset($result->headers['X-XRDS-Location'])) {
-          $xrds_url = $result->headers['X-XRDS-Location'];
-        }
-        else {
-          // Look for meta http-equiv link in HTML head
-          $xrds_url = _openid_meta_httpequiv('X-XRDS-Location', $result->data);
-        }
-        if (!empty($xrds_url)) {
-          $headers = array('Accept' => 'application/xrds+xml');
-          //TODO
-          $xrds_result = openid_http_request($xrds_url, $headers);
-          if (!isset($xrds_result->error)) {
-            $services = xrds_parse($xrds_result->data);
-          }
-        }
-      }
-
-      // Check for HTML delegation
-      if (count($services) == 0) {
-        // Look for 2.0 links
-        $uri = _openid_link_href('openid2.provider', $result->data);
-        $delegate = _openid_link_href('openid2.local_id', $result->data);
-        $version = 2;
-
-        // 1.0 links
-        if (empty($uri)) {
-          $uri = _openid_link_href('openid.server', $result->data);
-          $delegate = _openid_link_href('openid.delegate', $result->data);
-          $version = 1;
-        }
-        if (!empty($uri)) {
-          $services[] = array('uri' => $uri, 'delegate' => $delegate, 'version' => $version);
-        }
-      }
-    }
-  }
-  return $services;
-}
-
-/**
- * Attempt to create a shared secret with the OpenID Provider.
- *
- * @param $op_endpoint URL of the OpenID Provider endpoint.
- *
- * @return $assoc_handle The association handle.
- */
-function openid_association($op_endpoint) {
-
-  // Remove Old Associations:
-  //TODO
-  $openid_association = Database::get_main_table(TABLE_MAIN_OPENID_ASSOCIATION);
-  api_sql_query("DELETE FROM $openid_association WHERE created + expires_in < %d", time());
-
-  // Check to see if we have an association for this IdP already
-  $assoc_handle = api_sql_query("SELECT assoc_handle FROM $openid_association WHERE idp_endpoint_uri = '%s'", $op_endpoint);
-  if (Database::num_rows($assoc_handle)<=1) {
-    $mod = OPENID_DH_DEFAULT_MOD;
-    $gen = OPENID_DH_DEFAULT_GEN;
-    $r = _openid_dh_rand($mod);
-    $private = bcadd($r, 1);
-    $public = bcpowmod($gen, $private, $mod);
-
-    // If there is no existing association, then request one
-    $assoc_request = openid_association_request($public);
-    $assoc_message = _openid_encode_message(_openid_create_message($assoc_request));
-    $assoc_headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
-    //TODO
-    $assoc_result = openid_http_request($op_endpoint, $assoc_headers, 'POST', $assoc_message);
-    if (isset($assoc_result->error)) {
-      return FALSE;
-    }
-
-    $assoc_response = _openid_parse_message($assoc_result->data);
-    if (isset($assoc_response['mode']) && $assoc_response['mode'] == 'error') {
-        return FALSE;
-    }
-
-    if ($assoc_response['session_type'] == 'DH-SHA1') {
-      $spub = _openid_dh_base64_to_long($assoc_response['dh_server_public']);
-      $enc_mac_key = base64_decode($assoc_response['enc_mac_key']);
-      $shared = bcpowmod($spub, $private, $mod);
-      $assoc_response['mac_key'] = base64_encode(_openid_dh_xorsecret($shared, $enc_mac_key));
-    }
-    //TODO
-   	$openid_association = Database::get_main_table(TABLE_MAIN_OPENID_ASSOCIATION);
-    api_sql_query(sprintf("INSERT INTO $openid_association (idp_endpoint_uri, session_type, assoc_handle, assoc_type, expires_in, mac_key, created) VALUES('%s', '%s', '%s', '%s', %d, '%s', %d)",
-             $op_endpoint, $assoc_response['session_type'], $assoc_response['assoc_handle'], $assoc_response['assoc_type'], $assoc_response['expires_in'], $assoc_response['mac_key'], time()));
-
-    $assoc_handle = $assoc_response['assoc_handle'];
-  }
-
-  return $assoc_handle;
-}
-
-/**
- * ?
- */
-function openid_association_request($public) {
-  require_once(api_get_path(SYS_CODE_PATH).'auth/openid/openid.conf.php');
-
-  $request = array(
-    'openid.ns' => OPENID_NS_2_0,
-    'openid.mode' => 'associate',
-    'openid.session_type' => 'DH-SHA1',
-    'openid.assoc_type' => 'HMAC-SHA1'
-  );
-
-  if ($request['openid.session_type'] == 'DH-SHA1' || $request['openid.session_type'] == 'DH-SHA256') {
-    $cpub = _openid_dh_long_to_base64($public);
-    $request['openid.dh_consumer_public'] = $cpub;
-  }
-
-  return $request;
-}
-
-/**
- * 
- */
-function openid_authentication_request($claimed_id, $identity, $return_to = '', $assoc_handle = '', $version = 2) {
-
-  $realm = ($return_to) ? $return_to : api_get_self();
-
-  $ns = ($version == 2) ? OPENID_NS_2_0 : OPENID_NS_1_0;
-  $request =  array(
-    'openid.ns' => $ns,
-    'openid.mode' => 'checkid_setup',
-    'openid.identity' => $identity,
-    'openid.claimed_id' => $claimed_id,
-    'openid.assoc_handle' => $assoc_handle,
-    'openid.return_to' => $return_to,
-  );
-
-  if ($version == 2) {
-    $request['openid.realm'] = $realm;
-  }
-  else {
-    $request['openid.trust_root'] = $realm;
-  }
-
-  // Simple Registration - we don't ask lastname and firstname because the only
-  // available similar data is "fullname" and we would have to guess where to split 
-  $request['openid.sreg.required'] = 'nickname,email';
-  $request['openid.ns.sreg'] = "http://openid.net/extensions/sreg/1.1";
-
-  //$request = array_merge($request, module_invoke_all('openid', 'request', $request));
-  //$request = array_merge($request);
-
-  return $request;
-}
-
-/**
- * Attempt to verify the response received from the OpenID Provider.
- *
- * @param $op_endpoint The OpenID Provider URL.
- * @param $response Array of repsonse values from the provider.
- *
- * @return boolean
- */
-function openid_verify_assertion($op_endpoint, $response) {
-
-  $valid = FALSE;
-
-	//TODO
-  $openid_association = Database::get_main_table(TABLE_MAIN_OPENID_ASSOCIATION);
-  $sql = sprintf("SELECT * FROM $openid_association WHERE assoc_handle = '%s'", $response['openid.assoc_handle']);
-  $res = api_sql_query($sql);
-  $association = Database::fetch_object($res);
-  if ($association && isset($association->session_type)) {
-    $keys_to_sign = explode(',', $response['openid.signed']);
-    $self_sig = _openid_signature($association, $response, $keys_to_sign);
-    if ($self_sig == $response['openid.sig']) {
-      $valid = TRUE;
-    }
-    else {
-      $valid = FALSE;
-    }
-  }
-  else {
-    $request = $response;
-    $request['openid.mode'] = 'check_authentication';
-    $message = _openid_create_message($request);
-    $headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
-    $result = openid_http_request($op_endpoint, $headers, 'POST', _openid_encode_message($message));
-    if (!isset($result->error)) {
-      $response = _openid_parse_message($result->data);
-      if (strtolower(trim($response['is_valid'])) == 'true') {
-        $valid = TRUE;
-      }
-      else {
-        $valid = FALSE;
-      }
-    }
-  }
-
-  return $valid;
-}
-
-/**
- * Make a HTTP request - This function has been copied straight over from Drupal 6 code (drupal_http_request)
- */
-function openid_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
-  $result = new stdClass();
-
-  // Parse the URL and make sure we can handle the schema.
-  $uri = parse_url($url);
-
-  switch ($uri['scheme']) {
-    case 'http':
-      $port = isset($uri['port']) ? $uri['port'] : 80;
-      $host = $uri['host'] . ($port != 80 ? ':'. $port : '');
-      $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
-      break;
-    case 'https':
-      // Note: Only works for PHP 4.3 compiled with OpenSSL.
-      $port = isset($uri['port']) ? $uri['port'] : 443;
-      $host = $uri['host'] . ($port != 443 ? ':'. $port : '');
-      $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20);
-      break;
-    default:
-      $result->error = 'invalid schema '. $uri['scheme'];
-      return $result;
-  }
-
-  // Make sure the socket opened properly.
-  if (!$fp) {
-    // When a network error occurs, we make sure that it is a negative number so
-    // it can clash with the HTTP status codes.
-    $result->code = -$errno;
-    $result->error = trim($errstr);
-    return $result;
-  }
-
-  // Construct the path to act on.
-  $path = isset($uri['path']) ? $uri['path'] : '/';
-  if (isset($uri['query'])) {
-    $path .= '?'. $uri['query'];
-  }
-
-  // Create HTTP request.
-  $defaults = array(
-    // RFC 2616: "non-standard ports MUST, default ports MAY be included".
-    // We don't add the port to prevent from breaking rewrite rules checking the
-    // host that do not take into account the port number.
-    'Host' => "Host: $host",
-    'User-Agent' => 'User-Agent: Dokeos (+http://dokeos.com/)',
-    'Content-Length' => 'Content-Length: '. strlen($data)
-  );
-
-  // If the server url has a user then attempt to use basic authentication
-  if (isset($uri['user'])) {
-    $defaults['Authorization'] = 'Authorization: Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : ''));
-  }
-
-  foreach ($headers as $header => $value) {
-    $defaults[$header] = $header .': '. $value;
-  }
-
-  $request = $method .' '. $path ." HTTP/1.0\r\n";
-  $request .= implode("\r\n", $defaults);
-  $request .= "\r\n\r\n";
-  if ($data) {
-    $request .= $data ."\r\n";
-  }
-  $result->request = $request;
-
-  fwrite($fp, $request);
-
-  // Fetch response.
-  $response = '';
-  while (!feof($fp) && $chunk = fread($fp, 1024)) {
-    $response .= $chunk;
-  }
-  fclose($fp);
-
-  // Parse response.
-  list($split, $result->data) = explode("\r\n\r\n", $response, 2);
-  $split = preg_split("/\r\n|\n|\r/", $split);
-
-  list($protocol, $code, $text) = explode(' ', trim(array_shift($split)), 3);
-  $result->headers = array();
-
-  // Parse headers.
-  while ($line = trim(array_shift($split))) {
-    list($header, $value) = explode(':', $line, 2);
-    if (isset($result->headers[$header]) && $header == 'Set-Cookie') {
-      // RFC 2109: the Set-Cookie response header comprises the token Set-
-      // Cookie:, followed by a comma-separated list of one or more cookies.
-      $result->headers[$header] .= ','. trim($value);
-    }
-    else {
-      $result->headers[$header] = trim($value);
-    }
-  }
-
-  $responses = array(
-    100 => 'Continue', 101 => 'Switching Protocols',
-    200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',
-    300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect',
-    400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed',
-    500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported'
-  );
-  // RFC 2616 states that all unknown HTTP codes must be treated the same as the
-  // base code in their class.
-  if (!isset($responses[$code])) {
-    $code = floor($code / 100) * 100;
-  }
-
-  switch ($code) {
-    case 200: // OK
-    case 304: // Not modified
-      break;
-    case 301: // Moved permanently
-    case 302: // Moved temporarily
-    case 307: // Moved temporarily
-      $location = $result->headers['Location'];
-
-      if ($retry) {
-        $result = openid_http_request($result->headers['Location'], $headers, $method, $data, --$retry);
-        $result->redirect_code = $result->code;
-      }
-      $result->redirect_url = $location;
-
-      break;
-    default:
-      $result->error = $text;
-  }
-
-  $result->code = $code;
-  return $result;
+<?php
+/**
+ * OpenID login method
+ * 
+ * The OpenID login method relies on authentication servers providing a public
+ * URL that can confirm the identity of a person, thus avoiding the spread
+ * use of password transmissions over non-secure lines (for Dokeos, it is a
+ * good way of avoiding password theft)
+ */
+/**
+ * Initialisation
+ */
+require_once 'openid.conf.php';
+require_once 'openid.lib.php';
+require_once 'xrds.lib.php';
+
+function openid_form() 
+{
+	return '<div class="menusection"><span class="menusectioncaption">'.get_lang('OpenIdAuthentication').'</span><form name="openid_login" method="post"><label for="openid_url">'.get_lang('OpenIDURL').' <a href="main/auth/openid/whatis.php" title="'.get_lang('OpenIDWhatIs').'">'.Display::return_icon('info3.gif',get_lang('Info')).'</a></label><input type="text" id="openid_url" name="openid_url" style="background: url(main/img/openid_small_logo.png) no-repeat; background-color: #fff; background-position: 0 50%; padding-left:18px;" value="http://"></input><input type="submit" name="openid_login" value="'.get_lang('Enter').'" /><br /><br /></form></div>';
+}
+
+/**
+ * The initial step of OpenID authentication responsible for the following:
+ *  - Perform discovery on the claimed OpenID.
+ *  - If possible, create an association with the Provider's endpoint.
+ *  - Create the authentication request.
+ *  - Perform the appropriate redirect.
+ *
+ * @param $claimed_id The OpenID to authenticate
+ * @param $return_to The endpoint to return to from the OpenID Provider
+ */
+function openid_begin($claimed_id, $return_to = '', $form_values = array()) 
+{
+
+  $claimed_id = _openid_normalize($claimed_id);
+
+  $services = openid_discovery($claimed_id);
+  if (count($services) == 0) {
+    echo 'Sorry, that is not a valid OpenID. Please ensure you have spelled your ID correctly.';
+    return;
+  }
+
+  $op_endpoint = $services[0]['uri'];
+  // Store the discovered endpoint in the session (so we don't have to rediscover).
+  $_SESSION['openid_op_endpoint'] = $op_endpoint;
+  // Store the claimed_id in the session (for handling delegation).
+  $_SESSION['openid_claimed_id'] = $claimed_id;
+  // Store the login form values so we can pass them to
+  // user_exteral_login later.
+  $_SESSION['openid_user_login_values'] = $form_values;
+
+  // If bcmath is present, then create an association
+  $assoc_handle = '';
+  if (function_exists('bcadd')) {
+    $assoc_handle = openid_association($op_endpoint);
+  }
+
+  // Now that there is an association created, move on
+  // to request authentication from the IdP
+  $identity = (!empty($services[0]['delegate'])) ? $services[0]['delegate'] : $claimed_id;
+  if (isset($services[0]['types']) && is_array($services[0]['types']) && in_array(OPENID_NS_2_0 .'/server', $services[0]['types'])) {
+    $identity = 'http://openid.net/identifier_select/2.0';
+  }
+  $authn_request = openid_authentication_request($claimed_id, $identity, $return_to, $assoc_handle, $services[0]['version']);
+
+  if ($services[0]['version'] == 2) {
+    openid_redirect($op_endpoint, $authn_request);
+  }
+  else {
+    openid_redirect_http($op_endpoint, $authn_request);
+  }
+}
+
+/**
+ * Completes OpenID authentication by validating returned data from the OpenID
+ * Provider.
+ *
+ * @param $response Array of returned from the OpenID provider (typically $_REQUEST).
+ *
+ * @return $response Response values for further processing with
+ *   $response['status'] set to one of 'success', 'failed' or 'cancel'.
+ */
+function openid_complete($response) 
+{
+  // Default to failed response
+  $response['status'] = 'failed';
+  if (isset($_SESSION['openid_op_endpoint']) && isset($_SESSION['openid_claimed_id'])) {
+    _openid_fix_post($response);
+    $op_endpoint = $_SESSION['openid_op_endpoint'];
+    $claimed_id = $_SESSION['openid_claimed_id'];
+    unset($_SESSION['openid_op_endpoint']);
+    unset($_SESSION['openid_claimed_id']);
+    if (isset($response['openid.mode'])) {
+      if ($response['openid.mode'] == 'cancel') {
+        $response['status'] = 'cancel';
+      }
+      else {
+        if (openid_verify_assertion($op_endpoint, $response)) {
+          $response['openid.identity'] = $claimed_id;
+          $response['status'] = 'success';
+        }
+      }
+    }
+  }
+  return $response;
+}
+
+/**
+ * Perform discovery on a claimed ID to determine the OpenID provider endpoint.
+ *
+ * @param $claimed_id The OpenID URL to perform discovery on.
+ *
+ * @return Array of services discovered (including OpenID version, endpoint
+ * URI, etc).
+ */
+function openid_discovery($claimed_id) {
+
+  $services = array();
+
+  $xrds_url = $claimed_id;
+  if (_openid_is_xri($claimed_id)) {
+    $xrds_url = 'http://xri.net/'. $claimed_id;
+  }
+  $url = @parse_url($xrds_url);
+  if ($url['scheme'] == 'http' || $url['scheme'] == 'https') {
+    // For regular URLs, try Yadis resolution first, then HTML-based discovery
+    $headers = array('Accept' => 'application/xrds+xml');
+    //TODO
+    $result = openid_http_request($xrds_url, $headers);
+
+    if (!isset($result->error)) {
+      if (isset($result->headers['Content-Type']) && preg_match("/application\/xrds\+xml/", $result->headers['Content-Type'])) {
+        // Parse XML document to find URL
+        $services = xrds_parse($result->data);
+      }
+      else {
+        $xrds_url = NULL;
+        if (isset($result->headers['X-XRDS-Location'])) {
+          $xrds_url = $result->headers['X-XRDS-Location'];
+        }
+        else {
+          // Look for meta http-equiv link in HTML head
+          $xrds_url = _openid_meta_httpequiv('X-XRDS-Location', $result->data);
+        }
+        if (!empty($xrds_url)) {
+          $headers = array('Accept' => 'application/xrds+xml');
+          //TODO
+          $xrds_result = openid_http_request($xrds_url, $headers);
+          if (!isset($xrds_result->error)) {
+            $services = xrds_parse($xrds_result->data);
+          }
+        }
+      }
+
+      // Check for HTML delegation
+      if (count($services) == 0) {
+        // Look for 2.0 links
+        $uri = _openid_link_href('openid2.provider', $result->data);
+        $delegate = _openid_link_href('openid2.local_id', $result->data);
+        $version = 2;
+
+        // 1.0 links
+        if (empty($uri)) {
+          $uri = _openid_link_href('openid.server', $result->data);
+          $delegate = _openid_link_href('openid.delegate', $result->data);
+          $version = 1;
+        }
+        if (!empty($uri)) {
+          $services[] = array('uri' => $uri, 'delegate' => $delegate, 'version' => $version);
+        }
+      }
+    }
+  }
+  return $services;
+}
+
+/**
+ * Attempt to create a shared secret with the OpenID Provider.
+ *
+ * @param $op_endpoint URL of the OpenID Provider endpoint.
+ *
+ * @return $assoc_handle The association handle.
+ */
+function openid_association($op_endpoint) {
+
+  // Remove Old Associations:
+  //TODO
+  $openid_association = Database::get_main_table(TABLE_MAIN_OPENID_ASSOCIATION);
+  api_sql_query("DELETE FROM $openid_association WHERE created + expires_in < %d", time());
+
+  // Check to see if we have an association for this IdP already
+  $assoc_handle = api_sql_query("SELECT assoc_handle FROM $openid_association WHERE idp_endpoint_uri = '%s'", $op_endpoint);
+  if (Database::num_rows($assoc_handle)<=1) {
+    $mod = OPENID_DH_DEFAULT_MOD;
+    $gen = OPENID_DH_DEFAULT_GEN;
+    $r = _openid_dh_rand($mod);
+    $private = bcadd($r, 1);
+    $public = bcpowmod($gen, $private, $mod);
+
+    // If there is no existing association, then request one
+    $assoc_request = openid_association_request($public);
+    $assoc_message = _openid_encode_message(_openid_create_message($assoc_request));
+    $assoc_headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
+    //TODO
+    $assoc_result = openid_http_request($op_endpoint, $assoc_headers, 'POST', $assoc_message);
+    if (isset($assoc_result->error)) {
+      return FALSE;
+    }
+
+    $assoc_response = _openid_parse_message($assoc_result->data);
+    if (isset($assoc_response['mode']) && $assoc_response['mode'] == 'error') {
+        return FALSE;
+    }
+
+    if ($assoc_response['session_type'] == 'DH-SHA1') {
+      $spub = _openid_dh_base64_to_long($assoc_response['dh_server_public']);
+      $enc_mac_key = base64_decode($assoc_response['enc_mac_key']);
+      $shared = bcpowmod($spub, $private, $mod);
+      $assoc_response['mac_key'] = base64_encode(_openid_dh_xorsecret($shared, $enc_mac_key));
+    }
+    //TODO
+   	$openid_association = Database::get_main_table(TABLE_MAIN_OPENID_ASSOCIATION);
+    api_sql_query(sprintf("INSERT INTO $openid_association (idp_endpoint_uri, session_type, assoc_handle, assoc_type, expires_in, mac_key, created) VALUES('%s', '%s', '%s', '%s', %d, '%s', %d)",
+             $op_endpoint, $assoc_response['session_type'], $assoc_response['assoc_handle'], $assoc_response['assoc_type'], $assoc_response['expires_in'], $assoc_response['mac_key'], time()));
+
+    $assoc_handle = $assoc_response['assoc_handle'];
+  }
+
+  return $assoc_handle;
+}
+
+/**
+ * ?
+ */
+function openid_association_request($public) {
+  require_once(api_get_path(SYS_CODE_PATH).'auth/openid/openid.conf.php');
+
+  $request = array(
+    'openid.ns' => OPENID_NS_2_0,
+    'openid.mode' => 'associate',
+    'openid.session_type' => 'DH-SHA1',
+    'openid.assoc_type' => 'HMAC-SHA1'
+  );
+
+  if ($request['openid.session_type'] == 'DH-SHA1' || $request['openid.session_type'] == 'DH-SHA256') {
+    $cpub = _openid_dh_long_to_base64($public);
+    $request['openid.dh_consumer_public'] = $cpub;
+  }
+
+  return $request;
+}
+
+/**
+ * 
+ */
+function openid_authentication_request($claimed_id, $identity, $return_to = '', $assoc_handle = '', $version = 2) {
+
+  $realm = ($return_to) ? $return_to : api_get_self();
+
+  $ns = ($version == 2) ? OPENID_NS_2_0 : OPENID_NS_1_0;
+  $request =  array(
+    'openid.ns' => $ns,
+    'openid.mode' => 'checkid_setup',
+    'openid.identity' => $identity,
+    'openid.claimed_id' => $claimed_id,
+    'openid.assoc_handle' => $assoc_handle,
+    'openid.return_to' => $return_to,
+  );
+
+  if ($version == 2) {
+    $request['openid.realm'] = $realm;
+  }
+  else {
+    $request['openid.trust_root'] = $realm;
+  }
+
+  // Simple Registration - we don't ask lastname and firstname because the only
+  // available similar data is "fullname" and we would have to guess where to split 
+  $request['openid.sreg.required'] = 'nickname,email';
+  $request['openid.ns.sreg'] = "http://openid.net/extensions/sreg/1.1";
+
+  //$request = array_merge($request, module_invoke_all('openid', 'request', $request));
+  //$request = array_merge($request);
+
+  return $request;
+}
+
+/**
+ * Attempt to verify the response received from the OpenID Provider.
+ *
+ * @param $op_endpoint The OpenID Provider URL.
+ * @param $response Array of repsonse values from the provider.
+ *
+ * @return boolean
+ */
+function openid_verify_assertion($op_endpoint, $response) {
+
+  $valid = FALSE;
+
+	//TODO
+  $openid_association = Database::get_main_table(TABLE_MAIN_OPENID_ASSOCIATION);
+  $sql = sprintf("SELECT * FROM $openid_association WHERE assoc_handle = '%s'", $response['openid.assoc_handle']);
+  $res = api_sql_query($sql);
+  $association = Database::fetch_object($res);
+  if ($association && isset($association->session_type)) {
+    $keys_to_sign = explode(',', $response['openid.signed']);
+    $self_sig = _openid_signature($association, $response, $keys_to_sign);
+    if ($self_sig == $response['openid.sig']) {
+      $valid = TRUE;
+    }
+    else {
+      $valid = FALSE;
+    }
+  }
+  else {
+    $request = $response;
+    $request['openid.mode'] = 'check_authentication';
+    $message = _openid_create_message($request);
+    $headers = array('Content-Type' => 'application/x-www-form-urlencoded; charset=utf-8');
+    $result = openid_http_request($op_endpoint, $headers, 'POST', _openid_encode_message($message));
+    if (!isset($result->error)) {
+      $response = _openid_parse_message($result->data);
+      if (strtolower(trim($response['is_valid'])) == 'true') {
+        $valid = TRUE;
+      }
+      else {
+        $valid = FALSE;
+      }
+    }
+  }
+
+  return $valid;
+}
+
+/**
+ * Make a HTTP request - This function has been copied straight over from Drupal 6 code (drupal_http_request)
+ */
+function openid_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3) {
+  $result = new stdClass();
+
+  // Parse the URL and make sure we can handle the schema.
+  $uri = parse_url($url);
+
+  switch ($uri['scheme']) {
+    case 'http':
+      $port = isset($uri['port']) ? $uri['port'] : 80;
+      $host = $uri['host'] . ($port != 80 ? ':'. $port : '');
+      $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15);
+      break;
+    case 'https':
+      // Note: Only works for PHP 4.3 compiled with OpenSSL.
+      $port = isset($uri['port']) ? $uri['port'] : 443;
+      $host = $uri['host'] . ($port != 443 ? ':'. $port : '');
+      $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20);
+      break;
+    default:
+      $result->error = 'invalid schema '. $uri['scheme'];
+      return $result;
+  }
+
+  // Make sure the socket opened properly.
+  if (!$fp) {
+    // When a network error occurs, we make sure that it is a negative number so
+    // it can clash with the HTTP status codes.
+    $result->code = -$errno;
+    $result->error = trim($errstr);
+    return $result;
+  }
+
+  // Construct the path to act on.
+  $path = isset($uri['path']) ? $uri['path'] : '/';
+  if (isset($uri['query'])) {
+    $path .= '?'. $uri['query'];
+  }
+
+  // Create HTTP request.
+  $defaults = array(
+    // RFC 2616: "non-standard ports MUST, default ports MAY be included".
+    // We don't add the port to prevent from breaking rewrite rules checking the
+    // host that do not take into account the port number.
+    'Host' => "Host: $host",
+    'User-Agent' => 'User-Agent: Dokeos (+http://dokeos.com/)',
+    'Content-Length' => 'Content-Length: '. strlen($data)
+  );
+
+  // If the server url has a user then attempt to use basic authentication
+  if (isset($uri['user'])) {
+    $defaults['Authorization'] = 'Authorization: Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : ''));
+  }
+
+  foreach ($headers as $header => $value) {
+    $defaults[$header] = $header .': '. $value;
+  }
+
+  $request = $method .' '. $path ." HTTP/1.0\r\n";
+  $request .= implode("\r\n", $defaults);
+  $request .= "\r\n\r\n";
+  if ($data) {
+    $request .= $data ."\r\n";
+  }
+  $result->request = $request;
+
+  fwrite($fp, $request);
+
+  // Fetch response.
+  $response = '';
+  while (!feof($fp) && $chunk = fread($fp, 1024)) {
+    $response .= $chunk;
+  }
+  fclose($fp);
+
+  // Parse response.
+  list($split, $result->data) = explode("\r\n\r\n", $response, 2);
+  $split = preg_split("/\r\n|\n|\r/", $split);
+
+  list($protocol, $code, $text) = explode(' ', trim(array_shift($split)), 3);
+  $result->headers = array();
+
+  // Parse headers.
+  while ($line = trim(array_shift($split))) {
+    list($header, $value) = explode(':', $line, 2);
+    if (isset($result->headers[$header]) && $header == 'Set-Cookie') {
+      // RFC 2109: the Set-Cookie response header comprises the token Set-
+      // Cookie:, followed by a comma-separated list of one or more cookies.
+      $result->headers[$header] .= ','. trim($value);
+    }
+    else {
+      $result->headers[$header] = trim($value);
+    }
+  }
+
+  $responses = array(
+    100 => 'Continue', 101 => 'Switching Protocols',
+    200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content',
+    300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect',
+    400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed',
+    500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported'
+  );
+  // RFC 2616 states that all unknown HTTP codes must be treated the same as the
+  // base code in their class.
+  if (!isset($responses[$code])) {
+    $code = floor($code / 100) * 100;
+  }
+
+  switch ($code) {
+    case 200: // OK
+    case 304: // Not modified
+      break;
+    case 301: // Moved permanently
+    case 302: // Moved temporarily
+    case 307: // Moved temporarily
+      $location = $result->headers['Location'];
+
+      if ($retry) {
+        $result = openid_http_request($result->headers['Location'], $headers, $method, $data, --$retry);
+        $result->redirect_code = $result->code;
+      }
+      $result->redirect_url = $location;
+
+      break;
+    default:
+      $result->error = $text;
+  }
+
+  $result->code = $code;
+  return $result;
 }

+ 6 - 30
main/coursecopy/classes/CourseBuilder.class.php

@@ -1,27 +1,5 @@
-<?php // $Id: CourseBuilder.class.php 22200 2009-07-17 19:47:58Z iflorespaz $
-/*
-==============================================================================
-	Dokeos - elearning and course management software
-
-	Copyright (c) 2004 Dokeos S.A.
-	Copyright (c) 2003 Ghent University (UGent)
-	Copyright (c) 2001 Universite catholique de Louvain (UCL)
-	Copyright (c) Bart Mollet (bart.mollet@hogent.be)
-
-	For a full list of contributors, see "credits.txt".
-	The full license can be read in "license.txt".
-
-	This program is free software; you can redistribute it and/or
-	modify it under the terms of the GNU General Public License
-	as published by the Free Software Foundation; either version 2
-	of the License, or (at your option) any later version.
-
-	See the GNU General Public License for more details.
-
-	Contact address: Dokeos, 44 rue des palais, B-1030 Brussels, Belgium
-	Mail: info@dokeos.com
-==============================================================================
-*/
+<?php
+/* For licensing terms, see /dokeos_license.txt */
 require_once ('Course.class.php');
 require_once ('Event.class.php');
 require_once ('Link.class.php');
@@ -62,6 +40,7 @@ class CourseBuilder
 		$this->course->type = $type;
 		$this->course->path = api_get_path(SYS_COURSE_PATH).$_course['path'].'/';
 		$this->course->backup_path = api_get_path(SYS_COURSE_PATH).$_course['path'];
+		$this->course->encoding = api_get_system_encoding(); //current platform encoding 
 	}
 	/**
 	 * Get the created course
@@ -89,14 +68,11 @@ class CourseBuilder
 		$this->build_glossarys();
 		//TABLE_LINKED_RESOURCES is the "resource" course table, which is deprecated, apparently
 		$table = Database :: get_course_table(TABLE_LINKED_RESOURCES);
-		foreach ($this->course->resources as $type => $resources)
-		{
-			foreach ($resources as $id => $resource)
-			{
+		foreach ($this->course->resources as $type => $resources) {
+			foreach ($resources as $id => $resource) {
 				$sql = "SELECT * FROM ".$table." WHERE source_type = '".$resource->get_type()."' AND source_id = '".$resource->get_id()."'";
 				$res = api_sql_query($sql, __FILE__, __LINE__);
-				while ($link = Database::fetch_object($res))
-				{
+				while ($link = Database::fetch_object($res)) {
 					$this->course->resources[$type][$id]->add_linked_resource($link->resource_type, $link->resource_id);
 				}
 			}

+ 4 - 2
main/coursecopy/classes/CourseRestorer.class.php

@@ -82,8 +82,7 @@ class CourseRestorer
 	 * which the resources should be stored. Default: Current Dokeos-course.
 	 */
 	function restore($destination_course_code = '')
-	{
-		
+	{		
 		if ($destination_course_code == '') {
 			$course_info = api_get_course_info();
 			$this->course->destination_db = $course_info['dbName'];
@@ -93,6 +92,9 @@ class CourseRestorer
 			$this->course->destination_db = $course_info['database'];
 			$this->course->destination_path = $course_info['directory'];
 		}
+		// platform encoding
+		$course_charset = $this->course->encoding; 
+		
 		$this->restore_links();
 		$this->restore_tool_intro();
 		$this->restore_events();

+ 4 - 1
main/css/blue_lagoon/jquery.tabs.css

@@ -31,6 +31,7 @@
 	display: block;
 	padding: 0 10px;
 	background: url(images/tab.png) no-repeat;
+	
 }
 .tabs-nav a {
 	position: relative;
@@ -61,7 +62,7 @@
 	height: 18px; /* IE 6 treats height as min-height */
 	min-height: 18px;
 	padding-top: 6px;
-	padding-right: 0;
+	padding-right: 0;	
 }
 *>.tabs-nav a span { /* hide from IE 6 */
 	width: auto;
@@ -93,4 +94,6 @@
 .tabs-loading em {
 	padding: 0 0 0 20px;
 	background: url(images/loading.gif) no-repeat 0 50%;
+	color: #A8A7A7;
+
 }

+ 13 - 8
main/css/cosmic_campus/default.css

@@ -237,10 +237,23 @@ a.breadcrumb0 {
 .courseslist {
 	margin-left: -25px;
 }
+
+/* user_portal course list */
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 .courses a {
 }
 .user_course_category {
@@ -253,14 +266,6 @@ a.breadcrumb0 {
 	padding: 5px;
 }
 
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
-
 .menu {
 	float: right;
 	width: 200px;

+ 10 - 8
main/css/delicious_bordeaux/default.css

@@ -148,6 +148,16 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
+}
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
 }
 /*****************************************************
  *  HEADER STYLES                                    *
@@ -1273,14 +1283,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 0 - 8
main/css/dokeos_blue/default.css

@@ -1273,14 +1273,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 8
main/css/dokeos_classic/default.css

@@ -150,7 +150,18 @@ input[text] {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1327,14 +1338,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 8
main/css/dokeos_classic_2D/default.css

@@ -130,7 +130,18 @@ input.link_alike:hover {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*
 ==============================================================================
 	HEADER STYLES
@@ -1318,14 +1329,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-
-.session_course_item .courses {
-	height:22px;
-}
 /*
 ==============================================================================
     DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION

+ 11 - 7
main/css/empire_green/default.css

@@ -148,7 +148,18 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1273,13 +1284,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 8
main/css/fruity_orange/default.css

@@ -148,7 +148,18 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1273,14 +1284,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 12 - 7
main/css/medical/default.css

@@ -168,7 +168,18 @@ input[text] {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1309,13 +1320,7 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
+
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 7
main/css/public_admin/default.css

@@ -169,7 +169,18 @@ input[text] {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1323,13 +1334,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 7
main/css/royal_purple/default.css

@@ -148,7 +148,18 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1273,13 +1284,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 13 - 12
main/css/silver_line/default.css

@@ -81,12 +81,20 @@ ul {
 }
 /* user_portal course list */
 .courses {
-	font-weight: bold;
-	list-style: none;
-	margin-bottom: .2em;
-	font-family: arial, sans-serif, sans;
-	font-size: 110%;
+	list-style-type: none;
+	margin-bottom: 5px;
+	height: 30px;	
+}
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
 }
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 #main {
 	font-size: 89%;
 	width: 96%;
@@ -145,13 +153,6 @@ ul {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /*
 ==============================================================================
 	HEADER STYLES

+ 11 - 7
main/css/sober_brown/default.css

@@ -170,7 +170,18 @@ input[text] {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1298,13 +1309,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 7
main/css/steel_grey/default.css

@@ -148,7 +148,18 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1273,13 +1284,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 11 - 7
main/css/tasty_olive/default.css

@@ -148,7 +148,18 @@ input[type="text"]:focus, input[type="password"]:focus, textarea:focus {
 .courses {
 	list-style-type: none;
 	margin-bottom: 5px;
+	height: 30px;	
 }
+/* user_portal session list */
+.session_course_item .courses {
+	margin-bottom: 5px;
+	height:35px;
+}
+.session_course_item {
+	/* padding: 0px; */
+	margin: 0px;
+}
+
 /*****************************************************
  *  HEADER STYLES                                    *
  *****************************************************/
@@ -1273,13 +1284,6 @@ div.admin_section h4 {
 }
 .session_box_coach {
 }
-.session_course_item {
-	/* padding: 0px; */
-	margin: 0px;
-}
-.session_course_item .courses {
-	height:22px;
-}
 /***************************************************************
  *  DOKEOS CONFIG SETTINGS OF THE PLATFORM ADMIN SECTION 	   *
  ***************************************************************/

+ 14 - 19
main/document/slideshowoptions.php

@@ -1,4 +1,4 @@
-<?php // $Id: slideshowoptions.php 21107 2009-05-30 16:27:09Z iflorespaz $ 
+<?php // $Id: slideshowoptions.php 22565 2009-08-02 21:12:59Z yannoo $ 
 /*
 ==============================================================================
 	Dokeos - elearning and course management software
@@ -158,7 +158,7 @@ echo '</div>';
 		}
 			?>>
 		</div>
-		<div class="formw"><?php echo get_lang('_no_resizing');?><br><?php echo get_lang('_no_resizing_comment');?>
+		<div class="formw"><?php echo get_lang('_no_resizing');?><br /><?php echo get_lang('_no_resizing_comment');?>
 		</div>
 	</div>
 	
@@ -178,32 +178,28 @@ echo '</div>';
 			?>>
 		</div>
 		<div class="formw">
-			<?php echo get_lang('_resizing');?><br><?php echo get_lang('_resizing_comment');?><br>
+			<?php echo get_lang('_resizing');?><br /><?php echo get_lang('_resizing_comment');?><br />
         <?php echo get_lang('_width');?>: 
 	    &nbsp;<input name="width" type="text" id="width" 
 		<?php 
-		if ($image_resizing=="resizing")
-			{
+		if ($image_resizing=="resizing") {
 			echo " value='".$width."'";
 			echo " class=\"enabled_input\"";
-			}
-		else
-			{echo " class=\"disabled_input\""; }
+	    } else {
+            echo " class=\"disabled_input\""; 
+        }
 		?> >        
-        <br>
+        <br />
         <?php echo get_lang('_height');?>: 
         &nbsp;&nbsp;&nbsp;&nbsp;<input name="height" type="text" id="height"
 		<?php 
-		if ($image_resizing=="resizing")
-			{
+		if ($image_resizing=="resizing") {
 			echo " value='".$height."'";
 			echo " class=\"enabled_input\"";
-			}
-		else
-			{echo " class=\"disabled_input\""; }
-
-		?>
-			>
+		} else {
+            echo " class=\"disabled_input\""; 
+        }
+		?> >
 		</div>
 	</div>	
 	<div class="row">
@@ -216,5 +212,4 @@ echo '</div>';
 	</div>	
 </form>
 <?php
-Display::display_footer();
-?>
+Display::display_footer();

+ 57 - 57
main/dropbox/dropbox_functions.inc.php

@@ -1,12 +1,10 @@
 <?php //$id: $
 /* For licensing terms, see /dokeos_license.txt */
-
 /**
 * This file contains additional dropbox functions. Initially there were some 
 * functions in the init files also but I have moved them over
 * to one file 		-- Patrick Cool <patrick.cool@UGent.be>, Ghent University
 */
-
 /**
 * This function is a wrapper function for the multiple actions feature.
 * @return	Mixed	If there is a problem, return a string message, otherwise nothing
@@ -137,13 +135,13 @@ function delete_category($action, $id)
 
 	// step 1: delete the category
 	$sql="DELETE FROM ".$dropbox_cnf['tbl_category']." WHERE cat_id='".Database::escape_string($id)."' AND $sentreceived='1'";
-	$result=api_sql_query($sql);
+	$result=Database::query($sql,__FILE__,__LINE__);
 
 	// step 2: delete all the documents in this category
 	$sql="SELECT * FROM ".$entries_table." WHERE cat_id='".Database::escape_string($id)."'";
-	$result=api_sql_query($sql);
+	$result=Database::query($sql,__FILE__,__LINE__);
 
-	while ($row=mysql_fetch_array($result))
+	while ($row=Database::fetch_array($result))
 	{
 		$dropboxfile=new Dropbox_Person( $_user['user_id'], $is_courseAdmin, $is_courseTutor);
 		if ($action=='deletereceivedcategory')
@@ -170,8 +168,8 @@ function display_move_form($part, $id, $target=array())
 {
 	echo '<div class="row"><div class="form_header">'.get_lang('MoveFileTo').'</div></div>';
 	echo '<form name="form1" method="post" action="'.api_get_self().'?view_received_category='.$_GET['view_received_category'].'&view_sent_category='.$_GET['view_sent_category'].'&view='.$_GET['view'].'">';
-	echo '<input type="hidden" name="id" value="'.$id.'">';
-	echo '<input type="hidden" name="part" value="'.$part.'">';
+	echo '<input type="hidden" name="id" value="'.Security::remove_XSS($id).'">';
+	echo '<input type="hidden" name="part" value="'.Security::remove_XSS($part).'">';
 	echo '
 			<div class="row">
 				<div class="label">
@@ -227,7 +225,7 @@ function store_move($id, $target, $part)
 						WHERE dest_user_id='".Database::escape_string($_user['user_id'])."'
 						AND file_id='".Database::escape_string($id)."'
 						";
-			api_sql_query($sql,__FILE__,__LINE__);
+			Database::query($sql,__FILE__,__LINE__);
 			$return_message=get_lang('ReceivedFileMoved');
 		}
 		if ($part=='sent')
@@ -236,7 +234,7 @@ function store_move($id, $target, $part)
 						WHERE uploader_id='".Database::escape_string($_user['user_id'])."'
 						AND id='".Database::escape_string($id)."'
 						";
-			api_sql_query($sql,__FILE__,__LINE__);
+			Database::query($sql,__FILE__,__LINE__);
 			$return_message=get_lang('SentFileMoved');
 		}
 	}
@@ -278,7 +276,7 @@ function display_action_options($part, $categories, $current_category=0)
 		echo '</optgroup>';
 	}
 	echo '</select>';
-	echo '<input type="submit" name="do_actions_'.$part.'" value="'.get_lang('Ok').'" />';
+	echo '<input type="submit" name="do_actions_'.Security::remove_XSS($part).'" value="'.get_lang('Ok').'" />';
 }
 
 /**
@@ -299,7 +297,7 @@ function display_file_checkbox($id, $part)
 	{
 		$checked='checked';
 	}
-	$return_value='<input type="checkbox" name="'.$part.'_'.$id.'" value="'.$id.'" '.$checked.' />';
+	$return_value='<input type="checkbox" name="'.Security::remove_XSS($part).'_'.Security::remove_XSS($id).'" value="'.Security::remove_XSS($id).'" '.$checked.' />';
 	return $return_value;
 }
 
@@ -325,8 +323,8 @@ function get_dropbox_categories($filter='')
 
 	$sql="SELECT * FROM ".$dropbox_cnf['tbl_category']." WHERE user_id='".$_user['user_id']."'";
 
-	$result=api_sql_query($sql);
-	while ($row=mysql_fetch_array($result))
+	$result=Database::query($sql,__FILE__,__LINE__);
+	while ($row=Database::fetch_array($result))
 	{
 		if(($filter=='sent' AND $row['sent']==1) OR ($filter=='received' AND $row['received']==1) OR $filter=='')
 		{
@@ -382,7 +380,7 @@ function store_addcategory()
 	{
 		// step 3a, we check if the category doesn't already exist
 		$sql="SELECT * FROM ".$dropbox_cnf['tbl_category']." WHERE user_id='".$_user['user_id']."' AND cat_name='".Database::escape_string(Security::remove_XSS($_POST['category_name']))."' AND received='".$received."' AND sent='".$sent."'";
-		$result=api_sql_query($sql);
+		$result=Database::query($sql,__FILE__,__LINE__);
 
 
 		// step 3b, we add the category if it does not exist yet.
@@ -390,7 +388,7 @@ function store_addcategory()
 		{
 			$sql="INSERT INTO ".$dropbox_cnf['tbl_category']." (cat_name, received, sent, user_id)
 					VALUES ('".Database::escape_string(Security::remove_XSS($_POST['category_name']))."', '".Database::escape_string($received)."', '".Database::escape_string($sent)."', '".Database::escape_string($_user['user_id'])."')";
-			api_sql_query($sql);
+			Database::query($sql,__FILE__,__LINE__);
 			return array('type' => 'confirmation', 'message'=>get_lang('CategoryStored'));
 		}
 		else
@@ -403,7 +401,7 @@ function store_addcategory()
 		$sql="UPDATE ".$dropbox_cnf['tbl_category']." SET cat_name='".Database::escape_string(Security::remove_XSS($_POST['category_name']))."', received='".Database::escape_string($received)."' , sent='".Database::escape_string($sent)."'
 				WHERE user_id='".Database::escape_string($_user['user_id'])."'
 				AND cat_id='".Database::escape_string(Security::remove_XSS($_POST['edit_id']))."'";
-		api_sql_query($sql);
+		Database::query($sql,__FILE__,__LINE__);
 		return array('type' => 'confirmation', 'message'=>get_lang('CategoryModified'));
 	}
 }
@@ -427,7 +425,7 @@ function display_addcategory_form($category_name='', $id='',$action)
 	{
 		// retrieve the category we are editing
 		$sql="SELECT * FROM ".$dropbox_cnf['tbl_category']." WHERE cat_id='".Database::escape_string($id)."'";
-		$result=api_sql_query($sql);
+		$result=Database::query($sql,__FILE__,__LINE__);
 		$row=Database::fetch_array($result);
 
 		if ($category_name=='') // after an edit with an error we do not want to return to the original name but the name we already modified. (happens when createinrecievedfiles AND createinsentfiles are not checked)
@@ -485,7 +483,7 @@ function display_addcategory_form($category_name='', $id='',$action)
 	{
 		echo '<span class="form_error">'.get_lang('CategoryAlreadyExistsEditIt').'<span><br />';
 	}	
-	echo '			<input type="text" name="category_name" value="'.$category_name.'" />
+	echo '			<input type="text" name="category_name" value="'.Security::remove_XSS($category_name).'" />
 				</div>
 			</div>';
 	
@@ -503,7 +501,7 @@ function display_addcategory_form($category_name='', $id='',$action)
 					<span class="form_required">*</span> <small>'.get_lang('ThisFieldIsRequired').'</small>
 				</div>
 			</div>';	
-	echo "</form>";
+	echo '</form>';
 	echo '<div style="clear: both;"></div>';
 }
 
@@ -520,7 +518,7 @@ function display_add_form()
 	$token = Security::get_token();
 	$dropbox_person = new Dropbox_Person( $_user['user_id'], $is_courseAdmin, $is_courseTutor);
 	?>
-	<form method="post" action="index.php?view_received_category=<?php echo $_GET['view_received_category']; ?>&view_sent_category=<?php echo $_GET['view_sent_category']; ?>&view=<?php echo $_GET['view']; ?>&<?php echo "origin=$origin"."&".api_get_cidreq(); ?>" enctype="multipart/form-data" onsubmit="return checkForm(this)">
+	<form method="post" action="index.php?view_received_category=<?php echo Security::remove_XSS($_GET['view_received_category']); ?>&view_sent_category=<?php echo Security::remove_XSS($_GET['view_sent_category']); ?>&view=<?php echo Security::remove_XSS($_GET['view']); ?>&<?php echo "origin=$origin"."&".api_get_cidreq(); ?>" enctype="multipart/form-data" onsubmit="return checkForm(this)">
 	
 	<div class="row"><div class="form_header"><?php echo get_lang('UploadNewFile'); ?></div></div>
 	
@@ -536,7 +534,7 @@ function display_add_form()
 				<?php
 				if ($origin=='learnpath')
 				{
-					echo "<input type='hidden' name='origin' value='learnpath' />";
+					echo '<input type="hidden" name="origin" value="learnpath" />';
 				}
 				?>
 		</div>
@@ -686,12 +684,12 @@ function getUserNameFromId ( $id)  // RH: Mailing: return 'Mailing ' + id
     {
 	    return dropbox_lang("mailingAsUsername", "noDLTT") . $mailingId;
     }
-
+    $id = intval($id);
     $sql = "SELECT CONCAT(lastname,' ', firstname) AS name
 			FROM " . dropbox_cnf("tbl_user") . "
-			WHERE user_id='" . addslashes( $id) . "'";
-    $result = api_sql_query($sql,__FILE__,__LINE__);
-    $res = mysql_fetch_array( $result);
+			WHERE user_id='$id'";
+    $result = Database::query($sql,__FILE__,__LINE__);
+    $res = Database::fetch_array( $result);
 
     if ( $res == FALSE) return FALSE;
     return stripslashes( $res["name"]);
@@ -703,11 +701,12 @@ function getUserNameFromId ( $id)  // RH: Mailing: return 'Mailing ' + id
 */
 function getLoginFromId ( $id)
 {
+    $id = intval($id);
     $sql = "SELECT username
 			FROM " . dropbox_cnf("tbl_user") . "
-			WHERE user_id='" . addslashes( $id) . "'";
-    $result =api_sql_query($sql,__FILE__,__LINE__);
-    $res = mysql_fetch_array( $result);
+			WHERE user_id='$id'";
+    $result =Database::query($sql,__FILE__,__LINE__);
+    $res = Database::fetch_array( $result);
     if ( $res == FALSE) return FALSE;
     return stripslashes( $res["username"]);
 }
@@ -736,14 +735,14 @@ function removeUnusedFiles( )
 			FROM " . dropbox_cnf("tbl_file") . " f
 			LEFT JOIN " . dropbox_cnf("tbl_person") . " p ON f.id = p.file_id
 			WHERE p.user_id IS NULL";
-    $result = api_sql_query($sql,__FILE__,__LINE__);
-    while ( $res = mysql_fetch_array( $result))
+    $result = Database::query($sql,__FILE__,__LINE__);
+    while ( $res = Database::fetch_array( $result))
     {
 		//delete the selected files from the post and file tables
         $sql = "DELETE FROM " . dropbox_cnf("tbl_post") . " WHERE file_id='" . $res['id'] . "'";
-        $result1 = api_sql_query($sql,__FILE__,__LINE__);
+        $result1 = Database::query($sql,__FILE__,__LINE__);
         $sql = "DELETE FROM " . dropbox_cnf("tbl_file") . " WHERE id='" . $res['id'] . "'";
-        $result1 = api_sql_query($sql,__FILE__,__LINE__);
+        $result1 = Database::query($sql,__FILE__,__LINE__);
 
 		//delete file from server
         @unlink( dropbox_cnf("sysPath") . "/" . $res["filename"]);
@@ -759,19 +758,20 @@ function removeUnusedFiles( )
 * Mailing content files have uploader_id == mailing pseudo_id, a normal recipient,
 * and are visible initially to recipient and pseudo_id.
 *
-* @author Ren Haentjens, Ghent University
+* @author René Haentjens, Ghent University
 *
 * @todo check if this function is still necessary.
 */
 function getUserOwningThisMailing($mailingPseudoId, $owner = 0, $or_die = '')
 {
+    $mailingPseudoId = intval($mailingPseudoId);
     $sql = "SELECT f.uploader_id
 			FROM " . dropbox_cnf("tbl_file") . " f
 			LEFT JOIN " . dropbox_cnf("tbl_post") . " p ON f.id = p.file_id
 			WHERE p.dest_user_id = '" . $mailingPseudoId . "'";
-    $result = api_sql_query($sql,__FILE__,__LINE__);
+    $result = Database::query($sql,__FILE__,__LINE__);
 
-    if (!($res = mysql_fetch_array($result)))
+    if (!($res = Database::fetch_array($result)))
         die(dropbox_lang("generalError")." (code 901)");
 
     if ($owner == 0) return $res['uploader_id'];
@@ -791,23 +791,23 @@ function removeMoreIfMailing($file_id)
     //    for all content files, delete mailingPseudoId from person-table
     // 2. finding the owner (getUserOwningThisMailing) is no longer possible, so
     //    for all content files, replace mailingPseudoId by owner as uploader
-
+    $file_id = intval($file_id);
     $sql = "SELECT p.dest_user_id
 			FROM " . dropbox_cnf("tbl_post") . " p
 			WHERE p.file_id = '" . $file_id . "'";
-    $result = api_sql_query($sql,__FILE__,__LINE__);
+    $result = Database::query($sql,__FILE__,__LINE__);
 
-    if ( $res = mysql_fetch_array( $result))
+    if ( $res = Database::fetch_array( $result))
     {
 	    $mailingPseudoId = $res['dest_user_id'];
 	    if ( $mailingPseudoId > dropbox_cnf("mailingIdBase"))
 	    {
 	        $sql = "DELETE FROM " . dropbox_cnf("tbl_person") . " WHERE user_id='" . $mailingPseudoId . "'";
-	        $result1 = api_sql_query($sql,__FILE__,__LINE__);
+	        $result1 = Database::query($sql,__FILE__,__LINE__);
 
 	        $sql = "UPDATE " . dropbox_cnf("tbl_file") .
 	            " SET uploader_id='" . api_get_user_id() . "' WHERE uploader_id='" . $mailingPseudoId . "'";
-	        $result1 = api_sql_query($sql,__FILE__,__LINE__);
+	        $result1 = Database::query($sql,__FILE__,__LINE__);
         }
     }
 }
@@ -817,7 +817,7 @@ function removeMoreIfMailing($file_id)
 *
 * @todo check if this function is still necessary.
 *
-* @author Ren Haentjens, Ghent University
+* @author René Haentjens, Ghent University
 */
 function dropbox_lang($variable, $notrans = 'DLTT')
 {
@@ -1055,13 +1055,14 @@ function display_user_link($user_id, $name='')
 		{
 			$table_user = Database::get_main_table(TABLE_MAIN_USER);
 			$sql="SELECT * FROM $table_user WHERE user_id='".Database::escape_string($user_id)."'";
-			$result=api_sql_query($sql,__FILE__,__LINE__);
-			$row=mysql_fetch_array($result);
+			$result=Database::query($sql,__FILE__,__LINE__);
+			$row=Database::fetch_array($result);
 			return "<a href=\"../user/userInfo.php?uInfo=".$row['user_id']."\">".$row['firstname']." ".$row['lastname']."</a>";
 		}
 		else
 		{
-			return "<a href=\"../user/userInfo.php?uInfo=".$user_id."\">".$name."</a>";
+            $user_id = intval($user_id);
+			return "<a href=\"../user/userInfo.php?uInfo=".$user_id."\">".Security::remove_XSS($name)."</a>";
 		}
 	}
 	else
@@ -1101,8 +1102,8 @@ function feedback($array)
 function format_feedback($feedback)
 {
 	$output.=display_user_link($feedback['author_user_id']);
-	$output.='&nbsp;&nbsp;['.$feedback['feedback_date'].']<br>';
-	$output.='<div style="padding-top:6px">'.nl2br($feedback['feedback']).'</div><hr size="1" noshade/><br>';
+	$output.='&nbsp;&nbsp;['.$feedback['feedback_date'].']<br />';
+	$output.='<div style="padding-top:6px">'.nl2br($feedback['feedback']).'</div><hr size="1" noshade/><br />';
 	return $output;
 }
 
@@ -1122,8 +1123,8 @@ function feedback_form()
 	// we now check if the other users have not delete this document yet. If this is the case then it is useless to see the
 	// add feedback since the other users will never get to see the feedback.
 	$sql="SELECT * FROM ".$dropbox_cnf["tbl_person"]." WHERE file_id='".Database::escape_string($_GET['id'])."'";
-	$result=api_sql_query($sql,__LINE__, __FILE__);
-	$number_users_who_see_file=mysql_num_rows($result);
+	$result=Database::query($sql,__LINE__, __FILE__);
+	$number_users_who_see_file=Database::num_rows($result);
 	if ($number_users_who_see_file>1)
 	{
 		$return .= '<textarea name="feedback" style="width: 80%; height: 80px;"></textarea><br /><button type="submit" class="add" name="store_feedback" value="'.get_lang('Ok').'" 
@@ -1160,7 +1161,7 @@ function store_feedback()
 	{
 		$sql="INSERT INTO ".$dropbox_cnf['tbl_feedback']." (file_id, author_user_id, feedback, feedback_date) VALUES
 				('".Database::escape_string($_GET['id'])."','".Database::escape_string($_user['user_id'])."','".Database::escape_string($_POST['feedback'])."',NOW())";
-		api_sql_query($sql);
+		Database::query($sql,__FILE__,__LINE__);
 		return get_lang('DropboxFeedbackStored');
 	}
 }
@@ -1206,8 +1207,8 @@ function zip_download ($array)
 			WHERE file.id IN (".implode(', ',$array).")
 			AND file.id=person.file_id
 			AND person.user_id='".$_user['user_id']."'";
-	$result=api_sql_query($sql,__FILE__,__LINE__);
-	while ($row=mysql_fetch_array($result))
+	$result=Database::query($sql,__FILE__,__LINE__);
+	while ($row=Database::fetch_array($result))
 	{
 		$files[$row['filename']]=array('filename'=>$row['filename'],'title'=>$row['title'], 'author'=>$row['author'], 'description'=>$row['description']);
 	}
@@ -1454,8 +1455,8 @@ function get_total_number_feedback($file_id='')
 	global $dropbox_cnf;
 
 	$sql="SELECT COUNT(feedback_id) AS total, file_id FROM ".$dropbox_cnf['tbl_feedback']." GROUP BY file_id";
-	$result=api_sql_query($sql, __FILE__, __LINE__);
-	while ($row=mysql_fetch_array($result))
+	$result=Database::query($sql, __FILE__, __LINE__);
+	while ($row=Database::fetch_array($result))
 	{
 		$return[$row['file_id']]=$row['total'];
 	}
@@ -1526,8 +1527,7 @@ function get_last_tool_access($tool, $course_code='', $user_id='')
 				AND access_tool='".Database::escape_string($tool)."'
 				ORDER BY access_date DESC
 				LIMIT 1";
-	$result=api_sql_query($sql,__FILE__,__LINE__);
-	$row=mysql_fetch_array($result);
+	$result=Database::query($sql,__FILE__,__LINE__);
+	$row=Database::fetch_array($result);
 	return $row['access_date'];
-}
-?>
+}

+ 2 - 8
main/exercice/adminhp.php

@@ -134,18 +134,12 @@ $lstrComment = GetComment($hotpotatoesName);
 if($lstrComment=="")
 	$lstrComment = GetQuizName($hotpotatoesName,$documentPath);
 if($lstrComment=="")
-	$lstrComment = GetFileName($hotpotatoesName,$documentPath);
+	$lstrComment = basename($hotpotatoesName,$documentPath);
 
 echo $lstrComment;
 echo "\" size=40>&nbsp;";
 echo "<button type=\"submit\" class=\"save\" name=\"submit\" value=\"".get_lang('Ok')."\">".get_lang('Ok')."</button>";
 echo "<button type=\"button\" class=\"cancel\" name=\"cancel\" value=\"".get_lang('Cancel')."\" onclick=\"javascript:document.form1.newName.value='';\">".get_lang('Cancel')."</button>";
-
 echo "</form>";
 
-?>
-<?php
-
-Display::display_footer();
-
-?>
+Display::display_footer();

+ 8 - 22
main/exercice/exercice.php

@@ -836,33 +836,26 @@ if ($show == 'test') {
 ?>
 <table class="data_table">
   <?php
-
 	if (($is_allowedToEdit) and ($origin != 'learnpath')) {
 ?>
 	  <tr class="row_odd">
 	    <th colspan="3"><?php  echo get_lang('ExerciseName');?></th>
 	     <th><?php echo get_lang('QuantityQuestions');?></th>
 		 <!--<th>--><?php
-
 ?>
-
 <!--</th>-->
-		 <th><?php echo get_lang('Modify');?></th>
-	
+		 <th><?php echo get_lang('Modify');?></th>	
 	  </tr>
 	  <?php
-
 	} else {
+		//student only
 ?> <tr>
-	     <th colspan="3"><?php echo get_lang('ExerciseName');?></th>
+	     <th colspan="2"><?php echo get_lang('ExerciseName');?></th>
 	     <th><?php echo get_lang('QuantityQuestions');?></th>
-		 <th><?php echo get_lang('State');?></th>
-	
+		 <th><?php echo get_lang('State');?></th>	
 	  </tr>
 		<?php
-
 	}
-
 	// show message if no HP test to show
 	if (!($nbrExercises + $nbrHpTests)) {
 ?>
@@ -870,7 +863,6 @@ if ($show == 'test') {
 	    <td <?php echo ($is_allowedToEdit?'colspan="6"':'colspan="5"'); ?>><?php echo get_lang("NoEx"); ?></td>
 	  </tr>
 	  <?php
-
 	}
 	$i = 1;
 	// while list exercises
@@ -937,32 +929,26 @@ if ($show == 'test') {
 <!--" /></a>-->	    
 			<a href="exercice.php?choice=delete&exerciseId=<?php echo $row['id']; ?>" onclick="javascript:if(!confirm('<?php echo addslashes(api_htmlentities(get_lang('AreYouSureToDelete'),ENT_QUOTES,$charset)); echo " ".$row['title']; echo "?"; ?>')) return false;"> <img src="../img/delete.gif" border="0" alt="<?php echo api_htmlentities(get_lang('Delete'),ENT_QUOTES,$charset); ?>" /></a>					
 			<?php
-
 				//if active
 				if ($row['active']) {
 ?>
 	      		<a href="exercice.php?choice=disable&page=<?php echo $page; ?>&exerciseId=<?php echo $row['id']; ?>"> <img src="../img/visible.gif" border="0" alt="<?php echo api_htmlentities(get_lang('Deactivate'),ENT_QUOTES,$charset); ?>" /></a>
 	    		<?php
-
 				} else {
 					// else if not active
 ?>
 	      		<a href="exercice.php?choice=enable&page=<?php echo $page; ?>&exerciseId=<?php echo $row['id']; ?>"> <img src="../img/invisible.gif" border="0" alt="<?php echo api_htmlentities(get_lang('Activate'),ENT_QUOTES,$charset); ?>" /></a>
 	    		<?php
-
 				}
 				echo "</td>";
 				echo "</tr>\n";
 			} else { // student only
 ?>
 	          <tr>
-	            <td><?php echo ($i+($page*$limitExPage)).'.'; ?></td>
-	            <td>&nbsp;</td>
+	            <td><?php echo ($i+($page*$limitExPage)).'.'; ?></td>	            
 	            <?php $row['title']=api_parse_tex($row['title']);?>
 	            <td><a href="exercice_submit.php?<?php echo api_get_cidreq().$myorigin.$mylpid.$myllpitemid; ?>&exerciseId=<?php echo $row['id']; ?>"><?php echo $row['title']; ?></a></td>
-				 <td align="center"> <?php
-
-
+				<td align="center"> <?php
 				$exid = $row['id'];
 				//count number exercise questions
 				$sqlquery = "SELECT count(*) FROM $TBL_EXERCICE_QUESTION WHERE exercice_id = '" . Database :: escape_string($exid) . "'";
@@ -1066,7 +1052,7 @@ if ($show == 'test') {
 
 				$title = GetQuizName($path, $documentPath);
 				if ($title == '') {
-					$title = GetFileName($path);
+					$title = basename($path);
 				}
 				// prof only
 				if ($is_allowedToEdit) {
@@ -1345,7 +1331,7 @@ if ($_configuration['tracking_enabled'] && ($show == 'result')) {
 		for ($i = 0; $i < sizeof($hpresults); $i++) {
 			$title = GetQuizName($hpresults[$i][1], $documentPath);
 			if ($title == '') {
-				$title = GetFileName($hpresults[$i][1]);
+				$title = basename($hpresults[$i][1]);
 			}
 			echo '<tr>';
 			if ($is_allowedToEdit) {

+ 1 - 1
main/exercice/exercise_result.class.php

@@ -196,7 +196,7 @@ class ExerciseResult
 				$title = GetQuizName($hpresults[$i][1],$document_path);
 				if ($title =='')
 				{
-					$title = GetFileName($hpresults[$i][1]);
+					$title = basename($hpresults[$i][1]);
 				}
 				if(empty($user_id))
 				{

+ 30 - 39
main/exercice/exercise_submit_modal.php

@@ -1,4 +1,5 @@
 <?php
+/* For licensing terms, see /dokeos_license.txt */
 $language_file=array('exercice');
 include_once('../inc/global.inc.php');
 include api_get_path(INCLUDE_PATH) . 'reduced_header.inc.php';
@@ -21,41 +22,41 @@ require_once('question.class.php');
 require_once('answer.class.php');
 require_once('exercise.lib.php');
 
-if ( empty ( $exerciseResult ) ) {
+if (empty ($exerciseResult)) {
     $exerciseResult = $_SESSION['exerciseResult'];
 }
 
-if ( empty ( $exerciseResultCoordinates ) ) {
-    $exerciseResultCoordinates = $_REQUEST['exerciseResultCoordinates'];
+if (empty($exerciseResultCoordinates)) {
+    //$exerciseResultCoordinates = $_REQUEST['exerciseResultCoordinates'];
 }
-if ( empty ( $origin ) ) {
-    $origin = $_REQUEST['origin'];
+if (empty($origin)) {
+    $origin = Security::remove_XSS($_REQUEST['origin']);
 }
 
 $_SESSION['hotspot_coord']=array();
-$newquestionList=$_SESSION['newquestionList'];
-$questionList = $_SESSION['questionList'];
-$exerciseId=$_GET['exerciseId'];
-$exerciseType=$_GET['exerciseType'];
-$questionNum=$_GET['questionnum'];
-$nbrQuestions=$_GET['nbrQuestions'];
+$newquestionList= $_SESSION['newquestionList'];
+$questionList 	= $_SESSION['questionList'];
+$exerciseId		= intval($_GET['exerciseId']);
+$exerciseType	= intval($_GET['exerciseType']);
+$questionNum	= intval($_GET['questionnum']);
+$nbrQuestions	= intval($_GET['nbrQuestions']);
 
 //round-up the coordinates
 $coords = explode('/',$_GET['hotspot']);
 $user_array = '';
-foreach ($coords as $coord) {
-    list($x,$y) = explode(';',$coord);
-    $user_array .= round($x).';'.round($y).'/';
+if (is_array($coords) && count($coords)>0){
+	foreach ($coords as $coord) {
+	   	list($x,$y) = explode(';',$coord);
+    	$user_array .= round($x).';'.round($y).'/';
+	}
 }
 $user_array = substr($user_array,0,-1);
 
-if ( isset (  $_GET['choice'] ) ) 
-{ 
-    $choice_value = $_GET['choice'];
+if (isset( $_GET['choice'])){ 
+    $choice_value = intval($_GET['choice']);
 }
 // getting the options by js
-if (empty($choice_value) )
-{
+if (empty($choice_value)) {
 	echo '<script type="text/javascript">'."		
 		// this works for only radio buttons		
 		var f= self.parent.window.document.frm_exercise;
@@ -95,7 +96,7 @@ if (empty($choice_value) )
 		//alert(choice_js);						
 								
 	";		
-	echo 'window.location.href = "exercise_submit_modal.php?hotspotcoord="+ hotspotcoord + "&hotspot="+ hotspot + "&choice="+ choice_js + "&exerciseId='.$exerciseId.'&questionnum='.$questionNum.'&exerciseType='.$exerciseType.'&origin='.$origin.'gradebook='.$gradebook.'";</script>';
+	echo 'window.location.href = "exercise_submit_modal.php?hotspotcoord="+ hotspotcoord + "&hotspot="+ hotspot + "&choice="+ choice_js + "&exerciseId='.$exerciseId.'&questionnum='.$questionNum.'&exerciseType='.$exerciseType.'&origin='.$origin.'&gradebook='.$gradebook.'";</script>';
 }
 
 $choice=array();
@@ -111,21 +112,16 @@ if(!is_array($exerciseResult))
 
 
 // if the user has answered at least one question
-if(is_array($choice))
-{
-    if($exerciseType == 1)
-    {
+if(is_array($choice)) {
+    if($exerciseType == 1) {
         // $exerciseResult receives the content of the form.
         // Each choice of the student is stored into the array $choice
         $exerciseResult=$choice; 
-    }
-    else
-    {
+    } else {
         // gets the question ID from $choice. It is the key of the array
         list($key)=array_keys($choice);
         // if the user didn't already answer this question
-        if(!isset($exerciseResult[$key]))
-        {
+        if(!isset($exerciseResult[$key])) {
             // stores the user answer into the array
             $exerciseResult[$key]=$choice[$key];   
         }
@@ -242,8 +238,8 @@ if (!empty($choice_value))
 						//$_SESSION['exerciseResultCoordinates'][$questionId]=$exerciseResultCoordinates;
 						
 						// we compare only the delineation not the other points
-						$answer_question= $_SESSION['hotspot_coord'][1];	
-						$answerDestination=  $_SESSION['hotspot_dest'][1];
+						$answer_question	= $_SESSION['hotspot_coord'][1];	
+						$answerDestination	= $_SESSION['hotspot_dest'][1];
 						
                         $poly_user = convert_coordinates($user_answer,'/');
                         $poly_answer = convert_coordinates($answer_question,'|');
@@ -419,8 +415,7 @@ if (!empty($choice_value))
 
 $_SESSION['newquestionList']=$newquestionList;
 
-if ($choice_value==-1)
-{		
+if ($choice_value==-1) {		
 	$links. '<a href="#" onclick="self.parent.tb_remove();">'.get_lang('ChooseAnAnswer').'</a>';
 }
 
@@ -557,15 +552,11 @@ if ($links!='')
 	//echo '<a onclick="self.parent.tb_remove();" href="#" style="float:right;">'.get_lang('Close').'</a>';
 	echo '</div>';
 	$_SESSION['hot_spot_result']=$message; 
-}
-else
-{
-
+} else {
 	$questionNum++;
 	echo '<script>
 			self.parent.window.location.href = "exercice_submit.php?exerciseId='.$exerciseId.'&questionNum='.$questionNum.'&exerciseType='.$exerciseType.'&origin='.$origin.'";	  		 	
    			//self.parent.tb_remove();	  	
- 	 	</script>';
-	
+ 	 	</script>';	
 }
 ?>

+ 12 - 20
main/exercice/hotpotatoes.lib.php

@@ -54,7 +54,7 @@ function GetQuizName($fname,$fpath) {
 		if (file_exists($fpath.$fname)) {
 			if (!($fp = fopen($fpath.$fname, "r"))) {
 			//die("could not open Quiz input");
-				return GetFileName($fname);
+				return basename($fname);
 			}
 	
 			$contents = fread($fp, filesize($fpath.$fname));
@@ -79,12 +79,19 @@ function GetQuizName($fname,$fpath) {
  * Gets the comment about a file from the corresponding database record
  * @param	string	File path
  * @return	string	Comment from the database record
+ * Added conditional to the table if is empty.
  */
-function GetComment($path) {
+function GetComment($path,$course_code='') {
 	global $dbTable;
+	
+	if (!empty($course_code)) {		
+		$course_info = api_get_course_info($course_code);
+		$dbTable     = Database::get_course_table(TABLE_DOCUMENT,$course_info['dbName']);	
+	}
 	$path = Database::escape_string($path);
-	$query = "select comment from $dbTable where path='$path'";
+	$query = "select comment from $dbTable where path='$path'";		
 	$result = api_sql_query($query,__FILE__,__LINE__);
+	
 	while ($row = mysql_fetch_array($result)) {
 		return $row[0];
 	}
@@ -101,25 +108,11 @@ function SetComment($path,$comment) {
 	global $dbTable;
 	$path = Database::escape_string($path);
 	$comment = Database::escape_string($comment);
-	
 	$query = "UPDATE $dbTable set comment='$comment' where path='$path'";
 	$result = api_sql_query($query,__FILE__,__LINE__);
 	return "$result";
 }
 
-/**
- * Get the name of the file from a path (without the extension)
- *
- * This assumes the path is made of elements split by '/', not '\' or '\\'
- * @param	string	Path
- * @return	string	File name
- */
-function GetFileName($fname) {
-	$name = explode('/',$fname);
-	$name = $name[sizeof($name)-1];
-	return $name;
-}
-
 /**
  * Reads the file contents into a string
  * @param	string	Urlencoded path
@@ -165,7 +158,6 @@ function WriteFileCont($full_file_path,$content) {
  * Gets the name of an img whose path is given (without directories or extensions)
  * @param	string	An image tag (<img src="...." ...>)
  * @return	string	The image file name or an empty string
- * @uses GetFileName No comment
  */
 function GetImgName($imgtag) {	
     // select src tag from img tag
@@ -180,7 +172,7 @@ function GetImgName($imgtag) {
 		if ($src=="") {
 			return "";
 		} else {
-			$tmp_src = GetFileName($src) ;
+			$tmp_src = basename($src) ;
 			if ($tmp_src == "") {
 				return $src;
 			} else {
@@ -304,7 +296,7 @@ function ReplaceImgTag($content) {
 			else {
 
 				$prehref = $imgname;
-				$posthref = GetFileName($imgname);
+				$posthref = basename($imgname);
 				$newcontent = str_replace($prehref,$posthref,$newcontent);
 			}
 		}

+ 1 - 1
main/exercice/showinframes.php

@@ -84,7 +84,7 @@ WriteFileCont($full_file_path.$_user['user_id'].".t.html",$newcontent);
 	$newcontent = str_replace($prehref,$posthref,$newcontent);
 */
 
-$doc_url = GetFolderPath($doc_url).urlencode(GetFileName($doc_url));
+$doc_url = GetFolderPath($doc_url).urlencode(basename($doc_url));
 //	echo $documentWebPath.$doc_url.$_user['user_id'].".t.html";
 //	exit;
 ?>

+ 1 - 1
main/exercice/testheaderpage.php

@@ -18,7 +18,7 @@ $my_file=str_replace(array('../','\\..','\\0','..\\'),array('','','',''),urldeco
 
 $title = GetQuizName($my_file,$documentPath);
 if ($title =='') {
-	$title = GetFileName($my_file);
+	$title = basename($my_file);
 }
 $nameTools = $title;
 $noPHP_SELF=true;

+ 22 - 16
main/forum/forumfunction.inc.php

@@ -3898,23 +3898,28 @@ function get_thread_user_post($course_db, $thread_id, $user_id )
  	$j=0;
 	$forums = get_forums();	
 	krsort($forums);
-	$forum_results = '';	
+	$forum_results = '';
+	
  	foreach($forums as $forum) {	
 		if ($j<=4) { 		
-	 		$threads = get_threads($forum['forum_id']); 		
+	 		$threads = get_threads($forum['forum_id']);
+		
 	 		if (is_array($threads)) {	 			
 	 			/*echo Display::return_icon('forum.gif'); 		
 	 			echo $forum['forum_title'];*/
-	 			$my_course_db=explode('_',$course_db);
-	 			$my_course_code=$my_course_db[1];	 			 
+	 			//$my_course_db=explode('_',$course_db);
+	 			//$my_course_code=$my_course_db[1];
+	 			$my_course_code=CourseManager::get_course_id_by_database_name($course_db);	 			 
 	 			$i=0;
 	 			$hand_forums = ''; 	
 	 			$post_counter = 0;		 			
 		 		foreach($threads as $thread) {
 		 				if ($i<=4) {
 			 				$post_list = get_thread_user_post_limit($course_db, $thread['thread_id'], $user_id, 1);
+			 				
 			 				$post_counter = count($post_list);	
 			 				if (is_array($post_list) && count($post_list)>0) {
+			 					
 			 					$hand_forums.= '<div id="social-thread">';
 				 				$hand_forums.= Display::return_icon('forumthread.gif'); 	
 				 				$hand_forums.= $thread['thread_title'].' ';
@@ -3930,17 +3935,18 @@ function get_thread_user_post($course_db, $thread_id, $user_id )
 			 			$hand_forums.= '</div>';
 		 			}	
 		 			$i++;
-				}
-				if ($post_counter > 0 ) {
-					$forum_results .='<div id="social-forum">';
-	 				$forum_results .='<div class="clear"></div><br />';
-	 				$forum_results .='<div class="actions" style="margin-left:5px;margin-right:5px;">'.Display::return_icon('forum.gif').'&nbsp;&nbsp;&nbsp;&nbsp;'.$forum['forum_title'].'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div style="float:right;margin-top:-18px"><a href="../forum/viewforum.php?cidReq='.$my_course_code.'&gidReq=&forum='.$forum['forum_id'].' " >'.get_lang('SeeForum').'</a></div></div>';
-	 				$forum_results .='<br / >';					
-					$forum_results .=$hand_forums;
-					$forum_results .='</div>'; 
-				}
-	 		}	 		
- 		} $j++;		
+				
+					if ($post_counter > 0 ) {
+						$forum_results .='<div id="social-forum">';
+		 				$forum_results .='<div class="clear"></div><br />';
+		 				$forum_results .='<div class="actions" style="margin-left:5px;margin-right:5px;">'.Display::return_icon('forum.gif').'&nbsp;&nbsp;&nbsp;&nbsp;'.$forum['forum_title'].'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div style="float:right;margin-top:-18px"><a href="../forum/viewforum.php?cidReq='.$my_course_code.'&gidReq=&forum='.$forum['forum_id'].' " >'.get_lang('SeeForum').'</a></div></div>';
+		 				$forum_results .='<br / >';					
+						$forum_results .=$hand_forums;
+						$forum_results .='</div>'; 
+					}
+	 			}	 		
+ 			} $j++;		
+ 		}
  	}
  	return $forum_results;
  }
@@ -3957,7 +3963,7 @@ function get_thread_user_post_limit($course_db, $thread_id, $user_id, $limit=10)
 							AND posts.poster_id='".Database::escape_string($user_id)."'					
 						ORDER BY posts.post_id DESC LIMIT $limit ";
 	$result=api_sql_query($sql, __FILE__, __LINE__);
-	
+
 	while ($row=Database::fetch_array($result)) {
 		$row['status'] = '1';
 		$post_list[]=$row;

+ 1 - 1
main/gradebook/gradebook_result.class.php

@@ -177,7 +177,7 @@ class GradeBookResult
 				$return[$j+$i] = array();
 				$title = GetQuizName($hpresults[$i][1],$document_path);
 				if ($title =='') {
-					$title = GetFileName($hpresults[$i][1]);
+					$title = basename($hpresults[$i][1]);
 				}
 				if (empty($user_id)) {
 					$return[$j+$i]['user'] = $hpresults[$i][0];

BIN
main/img/wiki/assignment.gif


BIN
main/img/wiki/task.gif


BIN
main/img/wiki/works.gif


+ 11 - 6
main/inc/global.inc.php

@@ -219,6 +219,7 @@ require_once($lib_path.'display.lib.php');
 require_once($lib_path.'text.lib.php');
 require_once($lib_path.'security.lib.php');
 require_once($lib_path.'events.lib.inc.php');
+require_once($lib_path.'media.lib.php');
 
 // @todo: this shouldn't be done here. It should be stored correctly during installation
 if(empty($_configuration['statistics_database']) && $already_installed)
@@ -604,16 +605,20 @@ if (is_array($language_files)) {
 			
 			$tbl_admin_languages 	= Database :: get_main_table(TABLE_MAIN_LANGUAGE);	
 			$sql_sub_language='SELECT dokeos_folder FROM '.$tbl_admin_languages.' WHERE parent_id=(SELECT id FROM '.$tbl_admin_languages.' WHERE dokeos_folder="'.Database::escape_string($language_interface).'" AND  ISNULL(parent_id))';
+	
 			$rs_sub_language=Database::query($sql_sub_language,__FILE__,__LINE__);
-			$row_sub_language=Database::result($rs_sub_language,0,'dokeos_folder');
-			
-			$sub_langfile = $langpath.$row_sub_language.'/'.$language_file.'.inc.php';
+			$num_row_sub_language=Database::num_rows($rs_sub_language);
 			
 			if (file_exists($langfile)) {
-				include $langfile;
-				if (file_exists($sub_langfile)) {
-					include $sub_langfile;
+				include_once $langfile;
+				for ($i=0;$i<$num_row_sub_language;$i++) {
+					$row_sub_language=Database::result($rs_sub_language,$i,'dokeos_folder');
+					$sub_langfile = $langpath.$row_sub_language.'/'.$language_file.'.inc.php';
+					if (file_exists($sub_langfile)) {
+						include_once $sub_langfile;
+					}
 				}
+				
 			}
 		}	
 	} else {

+ 1 - 0
main/inc/lib/add_course.lib.inc.php

@@ -901,6 +901,7 @@ function update_Db_course($courseDbName)
 	//
 	$sql = "CREATE TABLE `".$TABLEWIKICONF . "` (
 		page_id int NOT NULL default 0,		
+		task text NOT NULL,
 		feedback1 text NOT NULL,
 		feedback2 text NOT NULL,
 		feedback3 text NOT NULL,

File diff suppressed because it is too large
+ 3453 - 0
main/inc/lib/asciimath/ASCIIMathML.js


+ 363 - 0
main/inc/lib/asciimath/asciimath.html

@@ -0,0 +1,363 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+          "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>ASCIIMathML: Math on the web for everyone</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+<style type="text/css">
+#menu, #title, #subtitle, #author, .display {text-align: center}
+body {font-family: Arial; background-color:beige}
+p,table {font-family: Times}
+</style>
+</head>
+<body>
+
+<div id="menu">
+| <a href="asciimath.html">Home Page</a> |
+<a href="asciimathsyntax.html">Syntax</a> |
+<a href="asciimathdemo.html">Try it</a> |
+<a href="asciimathcalculator.html">Calculator</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/mathml/asciimathdownload.html">Download</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathGraphs.html">Graphs</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathFAQ.html">ASCIIMath FAQ</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathMLSandbox.html">Sandbox</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathCommentsAndSuggestions.html">Comments</a> |
+</div>
+
+<hr/>
+
+<h2 id="title">
+ASCIIMathML.js (ver 2.0): Translating ASCII math notation to MathML
+and graphics</h2>
+
+<h4 align="center">
+Would you or your students like to <i>easily</i> produce
+<i>good-looking</i> math formulas on webpages<br/>
+using a <i>simple</i> calculator-style syntax and your 
+own ASCII or HTML editor?
+<br/>
+Here is a free multi-platform solution (and if you prefer it, 
+LaTeX-style formulas also work).
+</h4>
+
+<center>
+<b><font color="red">Now even easier to use:</font> 
+<font color="green"> just add one line to your 
+HTML file to load ASCIIMathML.js
+</font></b><p>
+ASCIIMathML.js is mentioned on the <a
+href="http://www.w3.org/Math/">MathML</a> page of the <a
+href="http://www.w3.org/">World Wide Web Consortium</a>, also on <a
+href="http://mathforge.net/index.jsp">mathforge.net</a> and <a
+href="http://mathforum.org/library/resource_types/typesetting/">The
+Math Forum.</a>
+</p>
+
+<font color="red"><b>New:</b></font> Now with <b>automatic math recognition</b>
+mode, better LaTeX support and graphics integration<br/>
+A <a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathMLMoodleFilter.html">Moodle filter</a> and a <a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathMLPmWikiCookbook.html">PmWiki cookbook</a> are also available<br/>
+<a href="http://www.pierce.ctc.edu/dlippman/asciimathtex/AMT.html">ASCIIMath Image Fallback Scripts</a> by David Lippman (including a Moodle filter)<br/>
+and a <a href="http://www.maths.nottingham.ac.uk/personal/drw/lm.html">LaTeXMathML</a> version of ASCIIMathML by <a href="http://www.maths.nottingham.ac.uk/personal/drw/">Dr Douglas R. Woodall</a> 
+(<a href="http://www.maths.nott.ac.uk/personal/drw/lmtest.html">examples</a>)
+<br />
+<a href="http://math.chapman.edu/~jipsen/asciencepad/asciencepad.html">ASciencePad</a> is a WYSIWYG editor that integrates
+
+<a href="http://www.tiddlywiki.com/">TiddlyWiki</a>, ASCIIMathML and ASCIIsvg graphs.<br />
+It's free and works locally (no installation or server required).<br />
+Useful information about <a 
+href="http://www.maths.ed.ac.uk/~james/ASCIIMathMLinfo.html">ASCIIMathML</a> 
+by <a href="http://www.maths.ed.ac.uk/~james/">James Gray</a>, including 
+a nice <a href="http://www.maths.ed.ac.uk/~james/ASCIIMathTutorial.html">tutorial</a>.<br />
+ASCIIMathML also works with <a href="http://www.meyerweb.com/eric/tools/s5/">S5</a> (CSS 
+Presentation slide show; <a href="http://math.chapman.edu/~jipsen/talks/MathFest2005/JipsenMathFestSlides2005.html">S5 ASCIIMath example</a>)<br/> 
+
+and in valid
+<a href="http://math.chapman.edu/~jipsen/mathml/asciimathandmathmlsvg.xhtml">
+XHTML pages with standard MathML and SVG</a> in several browsers.
+<br/>
+ASCIIMathML is being used with Movable Type, WordPress, phpBB, and many wikis.
+<br/>
+Also available: A PHP port of ASCIIMathML.js to <a 
+href="http://www.jcphysics.com/ASCIIMath/">ASCIIMathPHP</a> by <a 
+href="mailto:kc56@cornell.edu">Steven Chan</a>.
+</center>
+
+<p>
+
+This is the main page (HTML version) for the ASCIIMathML.js script which allows
+incorporating mathematical formulas on webpages with a minimum of
+fuss (just add one line to a webpage to load the script). 
+If you like what you see, choose <b>Save As...</b> in your browser
+and this page should work equally well locally on your machine.
+</p>
+
+<p class="display">
+<b>
+This page requires Internet Explorer 6 + <a href=
+"http://www.dessci.com/en/products/mathplayer/welcome.asp">MathPlayer</a>
+or Netscape7.1/Mozilla/Firefox.
+</b>
+</p>
+
+<p>
+ASCIIMathML.js is freely available under the <a
+href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser General Public
+License</a>. You can get your own copy from the <a href=
+"http://www.chapman.edu/~jipsen/mathml/asciimathdownload/">ASCIIMathML.js
+download page</a>. The script works with both HTML and XHTML webpages. 
+(The homepage for an XML 
+version is at <a href="asciimath.xml">asciimath.xml</a> but is no 
+longer maintained).
+
+</p>
+
+<p>
+If you use it on a webpage, please send me an email at <a
+href="mailto:jipsen@chapman.edu">jipsen@chapman.edu</a> with the URL
+so that I can add a link to it on the <a 
+href="http://math.chapman.edu/cgi-bin/mathxml.pl?Webpages_that_use_ASCIIMathML.js">users page</a>. 
+(Also send me an
+email if you have problems or would like to provide some feedback.)
+I'm currently using ASCIIMathML on a Wikiserver for lecture notes and
+<!--a href="http://math.chapman.edu/cgi-bin/mathxml.pl?Calculus_Text_Puzzles">Text
+Puzzles</a>. M-->my students are also using it in Moodle
+for writing and reading homework in their calculus class and 
+discrete mathematics class.
+<font color="red">
+If you just want to display MathML on HTML pages using 
+Netscape/Mozilla/Firefox or IE+MathPlayer, have a look at <a 
+href="http://www1.chapman.edu/~jipsen/mathml/mathhtml">mathhtmltest</a>
+(the page includes a 50 line JavaScript program that does the trick).
+</font>
+</p>
+
+<hr/>
+
+<p>
+<b>Let's test the ASCIIMathML.js translator on a simple example.</b>
+</p>
+
+<p>amath
+<b>Example:</b> Solving the quadratic equation. 
+Suppose a x^2+b x+c=0 and a!=0. We first 
+divide by \a to get x^2+b/a x+c/a=0. 
+
+Then we complete the square and obtain x^2+b/a x+(b/(2a))^2-(b/(2a))^2+c/a=0. 
+The first three terms factor to give (x+b/(2a))^2=(b^2)/(4a^2)-c/a.
+Now we take square roots on both sides and get
+x+b/(2a)=+-sqrt((b^2)/(4a^2)-c/a).
+
+Finally we subtract b/(2a) from both sides and simplify to get 
+the two solutions: x_(1,2)=(-b+-sqrt(b^2 - 4a c))/(2a)
+</p>
+endamath
+
+<p>
+<b>Here is the text that was typed in (<font color="red">using the new 
+auto-math-recognize mode</font> started by "a``math"):</b>
+
+</p>
+
+<pre>amath
+<b>Example:</b> Solving the quadratic equation.
+Suppose a x^2+b x+c=0 and a!=0. We first divide by \a to get x^2+b/a x+c/a=0. 
+
+Then we complete the square and obtain x^2+b/a x+(b/(2a))^2-(b/(2a))^2+c/a=0. 
+The first three terms factor to give (x+b/(2a))^2=(b^2)/(4a^2)-c/a.
+Now we take square roots on both sides and get x+b/(2a)=+-sqrt((b^2)/(4a^2)-c/a).
+
+Finally we move the b/(2a) to the right and simplify to get 
+the two solutions: x_(1,2)=(-b+-sqrt(b^2-4a c))/(2a)
+</pre>
+
+<hr/>
+
+<center>
+<b>
+If you don't believe this, copy the text and paste it on the 
+<a href="asciimathdemo.html">ASCIIMathML.js: Try it yourself</a> demo page.
+</b>
+
+</center>
+
+<hr/>
+
+<h4>
+Here are a few more examples:
+</h4>
+
+<table id="examples" border="5" cellpadding="10">
+<tr>
+<th>Type this</th>
+<th>See that</th>
+<th>Comment</th>
+</tr>
+
+<tr>
+<td>\`x^2+y_1+z_12^34\`</td>
+<td>`x^2+y_1+z_12^34`</td>
+<td>subscripts as in TeX, but numbers are treated as a unit</td>
+</tr>
+<tr>
+<td>\`sin^-1(x)\`</td>
+<td>`sin^-1(x)`</td>
+<td>function names are treated as constants</td>
+</tr>
+<tr>
+
+<td>\`d/dxf(x)=lim_(h->0)(f(x+h)-f(x))/h\`</td>
+<td>`d/dxf(x)=lim_(h->0)(f(x+h)-f(x))/h`</td>
+<td>complex subscripts are bracketed, displayed under lim</td>
+</tr>
+<tr>
+<td>\$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}\$</td>
+<td>$\frac{d}{dx}f(x)=\lim_{h\to 0}\frac{f(x+h)-f(x)}{h}$</td>
+<td>standard LaTeX notation is an alternative</td>
+</tr>
+<tr>
+<td>\`f(x)=sum_(n=0)^oo(f^((n))(a))/(n!)(x-a)^n\`</td>
+
+<td>`f(x)=sum_(n=0)^oo(f^((n))(a))/(n!)(x-a)^n`</td>
+<td>f^((n))(a) must be bracketed, else the numerator is only `a`</td>
+</tr>
+<tr>
+<td>\$f(x)=\sum_{n=0}^\infty\frac{f^{(n)}(a)}{n!}(x-a)^n\$</td>
+<td>$f(x)=\sum_{n=0}^\infty\frac{f^{(n)}(a)}{n!}(x-a)^n$</td>
+<td>standard LaTeX produces the same result</td>
+</tr>
+<tr>
+<td>\`int_0^1f(x)dx\`</td>
+<td>`int_0^1f(x)dx`</td>
+
+<td>subscripts must come before superscripts</td>
+</tr>
+<tr>
+<td>\`[[a,b],[c,d]]((n),(k))\`</td>
+<td>`[[a,b],[c,d]]((n),(k))`</td>
+<td>matrices and column vectors are simple to type</td>
+</tr>
+<tr>
+<td>\`x/x={(1,if x!=0),(text{undefined},if x=0):}\`</td>
+<td>`x/x={(1,if x!=0),(text{undefined},if x=0):}`</td>
+<td>piecewise defined function are based on matrix notation</td>
+
+</tr>
+<tr>
+<td>\`a//b\`</td>
+<td>`a//b`</td>
+<td>use // for inline fractions</td>
+</tr>
+<tr>
+<td>\`(a/b)/(c/d)\`</td>
+<td>`(a/b)/(c/d)`</td>
+<td>with brackets, multiple fraction work as expected</td>
+</tr>
+
+<tr>
+<td>\`a/b/c/d\`</td>
+<td>`a/b/c/d`</td>
+<td>without brackets the parser chooses this particular expression</td>
+</tr>
+<tr>
+<td>\`((a*b))/c\`</td>
+<td>`((a*b))/c`</td>
+<td>only one level of brackets is removed; * gives standard product</td>
+</tr>
+<tr>
+
+<td>\`sqrt sqrt root3x\`</td>
+<td>`sqrt sqrt root3x`</td>
+<td>spaces are optional, only serve to split strings that should not match</td>
+</tr>
+<tr>
+<td>\`<< a,b >> and {:(x,y),(u,v):}\`</td>
+<td>`<< a,b >> and {:(x,y),(u,v):}`</td>
+<td>angle brackets and invisible brackets</td>
+</tr>
+<tr>
+<td>\`(a,b]={x in RR | a < x <= b}\`</td>
+
+<td>`(a,b]={x in RR | a < x <= b}`</td>
+<td>grouping brackets don't have to match</td>
+</tr>
+<tr>
+<td>\`abc-123.45^-1.1\`</td>
+<td>`abc-123.45^-1.1`</td>
+<td>non-tokens are split into single characters,<br/>
+but decimal numbers are parsed with possible sign</td>
+</tr>
+
+<tr>
+<td>\`hat(ab) bar(xy) ulA vec v dotx ddot y\`</td>
+<td>`hat(ab) bar(xy) ulA vec v dotx ddot y`</td>
+<td>accents can be used on any expression (work well in IE)</td>
+</tr>
+<tr>
+<td>\`bb{AB3}.bbb(AB].cc(AB).fr{AB}.tt[AB].sf(AB)\`</td>
+<td>`bb{AB3}.bbb(AB].cc(AB).fr{AB}.tt[AB].sf(AB)`</td>
+<td>font commands; can use any brackets around argument</td>
+</tr>
+<tr>
+
+<td>\`stackrel"def"= or \stackrel{\Delta}{=}" "("or ":=)\`</td>
+<td>`stackrel"def"= or \stackrel{\Delta}{=}" "("or ":=)`</td>
+<td>symbols can be stacked</td>
+</tr>
+<tr>
+<td>\`{::}_(\ 92)^238U\`</td>
+<td>`{::}_(\ 92)^238U`</td>
+<td>prescripts simulated by subsuperscripts</td>
+</tr>
+</table>
+
+<p>
+If you are familiar with MathML, you can appreciate that this ASCII
+input form is less verbose and more readable. If you are familiar with
+TeX, this is still somewhat less cluttered. The aim is to have input
+notation that is close to graphing calculator notation, so that
+students are able to use it on webpages and in emails without having
+to learn another specialized syntax.
+</p>
+
+<p>
+For an explicit description of the input syntax see <a
+href="asciimathsyntax.html">ASCIIMathML.js Syntax and List of
+Constants</a>.
+</p>
+
+<p>
+<b>Acknowledgements:</b> Many thanks to the numerous people who have
+contributed to the fantastic MathML standard. Without such a
+well designed standard, a project like this would be impossible.<br/>
+
+Thanks to the many volunteers who implemented MathML in the
+Gecko layout engine for Netscape7/Mozilla/Firefox.<br/> 
+
+
+Thanks to the people at Design Science for producing the excellent
+MathPlayer plugin and making it freely available.<br/>
+
+Finally, thanks to the designers and implementors of JavaScript.  All
+these tools work together fairly seemlessly to allow us to put
+mathematical formulas on webpages in a convenient and inexpensive way.<br/>
+
+And thanks to Andrew White for making a logo for ASCIIMathML (see below).
+</p>
+<hr/>
+
+<div id="author">
+<a href="http://www.chapman.edu/~jipsen/">Peter Jipsen</a>, 
+<a href="http://www.chapman.edu/">Chapman University</a>, September 2007
+
+<a href="http://validator.w3.org/check/referer"><img border="0"
+src="http://www.w3.org/Icons/valid-html401"
+alt="Valid HTML 4.01!" height="31" width="88"></a>
+</div>
+
+<p><div class="display">
+<a style="color:white" href="../asciimath.html">
+<img src="asciimathml.jpeg" alt="ASCIIMathML"></a>
+</div>
+</body>
+</html>

+ 118 - 0
main/inc/lib/asciimath/asciimathcalculator.html

@@ -0,0 +1,118 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+          "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>ASCIIMath Calculator Demo</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+<!--script type="text/javascript">mathfontsize=".9em"</script-->
+<style type="text/css">
+#menu, #title, #subtitle, #author {text-align: center}
+body {font-family: Arial; background-color:beige}
+p,table {font-family: Times}
+</style>
+</head>
+<body>
+
+<div id="menu">
+| <a href="asciimath.html">Home Page</a> |
+<a href="asciimathsyntax.html">Syntax</a> |
+<a href="asciimathdemo.html">Try it</a> |
+<a href="asciimathcalculator.html">Calculator</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/mathml/asciimathdownload.html">Download</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathGraphs.html">Graphs</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathFAQ.html">ASCIIMath FAQ</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathMLSandbox.html">Sandbox</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathCommentsAndSuggestions.html">Comments</a> |
+</div>
+
+<hr/>
+
+<h2 id="title">
+ASCIIMath Scientific Calculator (ver 1.2)
+</h2>
+
+<h4 align="center">
+A free webpage calculator with live MathML display
+</h4>
+
+<h4 align="center">
+This page requires Internet Explorer 6+<a 
+href="http://www.dessci.com/en/products/mathplayer">MathPlayer</a> 
+or Mozilla/Firefox/Netscape 7+.
+</h4>
+
+<div class="ASCIIMathCalculator"></div>
+
+<p>
+More calculator areas:<br>
+<textarea id="in1" rows="2" cols="40" onkeyup="calculate('in1','out1')">
+2sin^-1(1)</textarea> &nbsp; <span id="out1"></span>
+<p/>
+
+<p>
+<textarea id="in2" rows="2" cols="30" 
+onkeyup="calculate('in2','out2');calculate('in3','out3')">
+a=5; b=4; c=-1; (-b+sqrt(b^2-4a*c))/(2a)
+</textarea> &nbsp; <span id="out2"></span>
+<br/>
+<textarea id="in3" rows="1" cols="30" 
+onkeyup="calculate('in2','out2');calculate('in3','out3')">
+(-b-sqrt(b^2-4a*c))/(2a)</textarea> &nbsp; <span id="out3"></span>
+
+</p>
+
+<p>
+<b>Note that this is dynamic HTML running locally on your machine.</b>
+<br/>
+Right-click on the output to copy or view the MathML code (or have it
+<b>spoken</b> in IE+MathPlayer).
+</p>
+
+<p>
+<b>Some technical remarks:</b> This calculator works only in radians.
+(Multiply angles by pi/180 to convert from degrees to radians.)
+<br/>
+
+The syntax is loosely based on JavaScript and a subset of ASCIIMathML.
+<br/>
+The multiplication symbol * can be omitted after a digit (0-9) 
+or a closing parenthesis.
+<br/>
+Available constants and functions: 
+<br/>
+&nbsp; &nbsp; +, -, *, /, ^, pi, e, sqrt(), ln(), abs(), sign(), 
+floor(), ceil(), n!, C(n,k), ran(a,b,n)
+<br/>
+&nbsp; &nbsp; sin(), cos(), tan(), sin^-1(), cos^-1(), tan^-1(), 
+sinh(), cosh(), tanh(), sinh^-1(), cosh^-1(), tanh^-1()
+<br/>
+&nbsp; &nbsp; sec(), csc(), cot(), sec^-1(), csc^-1(), cot^-1(),
+sech(), csch(), coth(), sech^-1(), csch^-1(), coth^-1()
+
+<br/>
+Values can be assigned to (legal JavaScript) variable names. 
+Use ";" to separate expressions.
+<br/>
+Any number of calculator textareas can be placed anywhere on <b>your own</b> 
+webpages.
+</p>
+ASCIIMathML and this calculator are freely available under the 
+<a href="http://www.gnu.org/licenses/lgpl.html">GNU Lesser General
+Public License</a>. Please include a link to <a
+href="http://asciimathml.sourceforge.net">asciimathml.sourceforge.net</a>
+on any webpage that makes use of them, and send a link of your webpage
+to <a href="mailto:jipsen@chapman.edu">jipsen@chapman.edu</a>.
+
+<hr/>
+
+<div id="author">
+<a href="http://www.chapman.edu/~jipsen/">Peter Jipsen</a>, 
+<a href="http://www.chapman.edu/">Chapman University</a>, May 2007
+
+<a href="http://validator.w3.org/check/referer"><img border="0"
+src="http://www.w3.org/Icons/valid-html401"
+alt="Valid HTML 4.01!" height="31" width="88"></a>
+</div>
+</body>
+</html>

+ 227 - 0
main/inc/lib/asciimath/asciimathchanges.txt

@@ -0,0 +1,227 @@
+Changes file for ASCIIMathML.js
+===============================
+
+Sep 27, 2007 Version 2.0
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML20.js)
+
+- included LaTeXMathML.js and ASCIIsvg.js in the ASCIIMathML script
+
+- changed license to GNU LGPL 2.1
+
+- Added auto-math-recognize mode (amath ... endamath)
+
+- Added some LaTeX environments and simple formatting
+
+- Created Moodle filter and PmWiki cookbook
+
+- Added MathML text labels to SVG graphs
+
+- Fixed SVG cursor tracking in Firefox
+
+- Added stroke/fillopacity to graphs
+
+- Simplified syntax for graph inclusion
+
+- SVG mouseevents are now added in the scope of the graph code
+
+- MathML fontsize can now be magnified relative to surrounding text
+
+-------------------------------
+
+Aug 7, 2005 Version 1.4.7
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML147.js)
+
+- changed IE MathML prefix from mml: to m: (default of MathPlayer, so now
+  <html> works without the xmlns attribute)
+
+- for IE the script now writes out the <object ...> and <?import ...> tags
+  simplifying the header file significantly 
+
+- script now uses a generic onload (by www.brothercake.com) so 
+  no need for onload="translate()" in <body> (but earlier pages still work)
+
+- ASCIIMathML.js can now be used on any HTML page by just adding one line to
+  load the script. So validating your HTML pages is now possible, and use
+  of HTML editors is simple.
+
+- added unparametrized macros: put <script>newcommand("short","long")</script>
+  on your webpage and each occurrence of "short" is replaced by "long"
+
+- added /_ (\angle) and :. (\therefore) as symbols
+
+- made an ASCIIMath plugin for Xinha HTML editor (see editor link on homepage)
+  with instant preview, template popup and builtin calculator
+
+-------------------------------
+
+Apr 23, 2005 Version 1.4.6
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML146.js)
+
+- added "showasciiformulaonhover" variable; if true then pointing at a MathML 
+  expression shows the ascii form that produces the expression
+
+- added "decimalsign" variable; default is "."
+
+- removed "separatetokens" option (to speed up token recognition)
+
+- changed |-, |=, |_, _| to |--, |==, |__, __| to avoid parsing problems
+  e.g. |-x|, |x|=a, ||A||_1 now parse as expected
+
+- changed parser so that "-" is unary if previous token is INFIX
+  e.g. now x^-y works like x^(-y) (but x-y is same as x - y)
+
+- added "spanclassAM" option; invoked by translate(true), all math should
+  then be delimited by <span class="AM">...</span>; translate() works as before
+
+-------------------------------
+
+Jan 30, 2005 Version 1.4.5
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML145.js)
+
+- added TEXT token type for \text{...}, \mbox{...} and "..."
+
+- changed sin, cos, tan, ..., lcm to UNARY type (func); now 1/sinx works
+
+- changed parser so that ^, _ have priority over /
+  now x_1/3^2 works like (x_1)/(3^2)
+
+-------------------------------
+
+Jan 14, 2005 Version 1.4.4
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML144.js)
+
+- added "mathfontfamily" variable (default "serif")
+
+- mathcolor and mathfontfamily can be "" to inherit values of surrounding text
+
+- added "AMdelimiter" variables to set math delimiters (default "`" and "$")
+
+- added LEFTRIGHT token type for "|"; now `|x|` displays like `{:|x|:}`;
+  a single | still parses as \mid e.g. in {x | x > 0}
+
+-------------------------------
+
+Dec 28, 2004 Version 1.4.3
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML143.js)
+
+- added mapsto |->
+
+- fixed a parsing error that was generated by incomplete fractions (1/)
+
+- fixed parsing of negative numbers (<mn>-1</mn> is now translated to
+  <mrow><mo>-</mo><mn>1</mn></mrow>)
+
+- added notifyIfNoMathML flag. If false, no note is inserted at top of page.
+
+- included ASCIIMathCalculator.js: a small script that implements a
+  webpage calculator with live MathML preview
+
+-------------------------------
+
+Nov 12, 2004 Version 1.4.2
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML142.js)
+
+- added constants for: setminus, vdots, ddots, glb, lub
+
+-------------------------------
+
+Aug 16, 2004 Version 1.4.1
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML141.js)
+
+- fixed a typo to make the check for MathML capability work correctly
+
+- added stackrel command (mover in MathML), e.g. stackrel{def}{=}
+
+- added := as binary relation to get spacing right in Mozilla/Firefox/Netscape
+
+-------------------------------
+
+July 13, 2004 Version 1.4
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML4.js)
+
+- cleaned up the js code, thanks to some very helpful suggestions by Alex V. 
+
+- most global variables prefixed with "AM" to avoid conflict with ASCIIsvg.js
+
+- added macro definition ability to define dx, dy, dz, ...
+  e.g. now dx is replaced by {d x}, so `d/dx` can be used rather than `d/(dx)`.
+  Users can add their own (parameterless) macros.
+
+- added check for MathML capability. If absent, inserts note at top of page.
+
+- unmatched right bracket no longer ends expression. E.g. in `cosx]_0^1`
+  the "]" is treated simply as a constant symbol (better to use `{:cosx]_0^1`).
+
+- numeric unicode entity names can be used for unnamed symbols, e.g. `&#x2270;`
+
+-------------------------------
+
+Mar 26, 2004 Version 1.3
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML3.js)
+
+- fixed parser so that unary/binary symbols without arguments are treated 
+  as constants (previously generated js error)
+
+- noticed that ASCIIMathML.js does not require XML, actually works in HTML
+  on multiple browsers (required no change to the script)
+
+- added `"any"` as alternative to `text{any}`
+
+- added  min, max  as standard function names (subscripts go underneath)
+
+- added o. (\odot) as symbol
+
+- added separatetokens flag: lowercase tokens must be separated by nonletters
+  (if true, `sinx` is a sequence of 4 variables, instead use `sin x`)
+  switched off by default, can be switched on (see top of ASCIIMathML.js)
+
+- added (experimental) doubleblankmathdelimiter so  a+b  is same as `a+b`
+  switched off by default, can be switched on (see top of ASCIIMathML.js)
+
+-------------------------------
+
+Feb 8, 2004 Version 1.2
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML2.js)
+
+- added accents: hat bar ul vec dot ddot
+
+- added sans-serif font: sf
+
+- both `...` and $...$ are now allowed as math delimiters
+
+- \$ and \` can now be used to insert $ or ` in plain text
+
+- `a text{ sometext }b` now shows the space around "sometext"
+
+- blocks of ASCIIMathML + text can be enclosed in comments <!-- -->
+  in which case blank lines are converted to paragraph breaks;
+  inside comments the < character can be used (does not cause XML error)
+  (use this "comment mode" with caution; future versions of IE or
+   Mozilla may not display it the same way)
+
+-------------------------------
+
+Jan 9, 2004 Version 1.1
+(at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML1.js)
+
+- added \vdash, \models (actually &vDash;!), \vartheta, \bigwedge, \bigvee,
+  \bigcup, \bigcap, \propto, \oint to symbol table, with ASCII equivalents
+
+- renamed "subset, supset" to their entity names "sube, supe", 
+  added "sub, sup" and their LaTeX equivalents \subset, \supset
+
+- updated webpages
+
+-------------------------------
+
+Jan 6, 2004 Version 1.0 
+(now at http://www.chapman.edu/~jipsen/mathml/ASCIIMathML0.js)
+
+- calligraphic, black board bold and fraktur fonts are finally working 
+  also in Mozilla/Netscape 7
+
+- added a download page
+
+- added GNU GPL notices
+
+===============================

+ 117 - 0
main/inc/lib/asciimath/asciimathdemo.html

@@ -0,0 +1,117 @@
+<html>
+<head>
+<title>ASCIIMathML.js demo</title>
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+<script type="text/javascript">
+translateOnLoad=false;
+function display() {
+  var str = document.getElementById("inputText").value;
+  var outnode = document.getElementById("outputNode");
+  var n = outnode.childNodes.length;
+  for (var i=0; i<n; i++)
+    outnode.removeChild(outnode.firstChild);
+  outnode.appendChild(document.createTextNode(str));
+  AMprocessNode(outnode);
+}
+</script>
+<style type="text/css">
+#menu, #title, #subtitle, #author {text-align: center}
+body {font-family: Arial; background-color:beige;}
+</style>
+</head>
+<body onload="display()">
+
+<div id="menu">
+| <a href="asciimath.html">Home Page</a> |
+<a href="asciimathsyntax.html">Syntax</a> |
+<a href="asciimathdemo.html">Try it</a> |
+<a href="asciimathcalculator.html">Calculator</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/mathml/asciimathdownload.html">Download</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathGraphs.html">Graphs</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathFAQ.html">ASCIIMath FAQ</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathMLSandbox.html">Sandbox</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathCommentsAndSuggestions.html">Comments</a> |
+</div>
+
+<hr/>
+
+<h2 id="title">
+ASCIIMathML.js: Try it yourself (HTML version)
+</h2>
+
+<center>
+<b>
+This page requires Internet Explorer 6+<a 
+href="http://www.dessci.com/en/products/mathplayer">MathPlayer</a> 
+or Mozilla/Firefox/Netscape 7+.
+</b>
+<p>
+Edit the formulas below (the display updates dynamically).
+If you know (La)TeX formula syntax, you can try some of that as well
+(LaTeX formulas work best when enclosed in $-signs).
+The "amath" token switches on the new auto-math-recognize mode.</p>
+
+<form>
+<textarea id="inputText" rows="10" cols="80" onkeyup="display()">
+amath
+
+Let's try some interesting formulas: E=m c^2
+and e^(i pi)=-1
+and AA x in CC (sin^2x+cos^2x=1)
+and one more: sum_(i=1)^n i^3=((n(n+1))/2)^2
+
+(add your own -- note that text-tokens are only recognized if separated by spaces)
+
+</textarea>
+</form>
+
+<p>
+<div id="outputNode"></div>
+</p>
+
+<hr/>
+<p>
+<b>Note that this is dynamic XHTML running locally on your machine!</b>
+<br>
+Right-click on an output formula to copy or view the MathML code.
+</p>
+</center>
+(Copy and paste the following lines to see what symbols they produce)<br/>
+<b>You can use the following ASCIIMathML constructs:</b> 
+<tt> `(x+1)/(x-1) x^(i+j) x_(ij) sqrt(x) root(n)(x) stackrel(+)(->) text(any) "any"`</tt><br/>
+<b>Operation symbols</b> 
+<tt> `+ - * ** // \\ xx -: @ o+ ox sum prod ^^ ^^^ vv vvv nn nnn uu uuu`</tt><br/>
+<b>Relation symbols</b>
+<tt> `= != &lt; &lt;= > >= -&lt; >- in !in sub sup sube supe -= ~= ~~ prop`</tt><br/>
+<b>Logical symbols</b><tt> `\and \or \not => if iff AA EE _|_ TT |-- |==`</tt><br/>
+<b>Miscellaneous symbols</b> 
+<tt> `int oint del grad +- O/ oo aleph ... cdots \  quad qquad diamond square |__ __| |~ ~| CC NN QQ RR ZZ`</tt><br/>
+<b>Standard functions</b> 
+<tt> `sin cos tan csc sec cot sinh cosh tanh log ln det dim lim mod gcd lcm`</tt><br/>
+<b>Grouping brackets</b><tt> `( ) [ ] { } (: :) {: :}` </tt> 
+<b>Arrows</b><tt> `uarr darr rarr -> larr harr rArr lArr hArr` </tt><br/>
+<b>Accents</b><tt> `hatx barx ulx vecx dotx ddotx` </tt>
+<b>Font commands</b><tt> `bbA bbbA ccA ttA frA sfA` </tt>
+<b>Matrices</b><tt> `[[a,b],[c,d]] ((1,0),(0,1))` </tt><br/>
+<b>Greek letters</b><tt> `alpha beta chi delta Delta epsi eta gamma Gamma
+iota kappa lambda Lambda mu nu omega Omega phi Phi pi Pi psi rho sigma Sigma 
+tau theta Theta upsilon xi Xi zeta`</tt> 
+
+<p>
+This demo page shows that ASCIIMathML.js can be used easily to
+dynamically preview mathematical formulas (client-side). E.g. here is a
+(beta) webpage that can be used to <b><a
+href="http://math.chapman.edu/email/">write and read
+mathematical emails and discussion group articles</a></b>. Since most
+email communication is still done with ASCII text (or at least not yet
+with XHTML), this is a reasonable (and inexpensive) solution for
+communicating with students in online math courses.
+</p>
+
+<hr/>
+<div id="author">
+<a href="http://www.chapman.edu/~jipsen/">Peter Jipsen</a>, 
+<a href="http://www.chapman.edu/">Chapman University</a>, September 2007
+</div>
+</body>
+</html>

+ 76 - 0
main/inc/lib/asciimath/asciimathextend.html

@@ -0,0 +1,76 @@
+<html>
+<head>
+<title>Extending ASCIIMathML</title>
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+
+<script type="text/javascript">
+define("!<=","\u2270")
+define("!>=","\u2271")
+newcommand("\\nle","\u2270")
+newcommand("\\nge","\u2271")
+</script>
+</head>
+<body bgcolor="beige">
+
+<h2>ASCIIMathML.js: Extending the symbol table</h2>
+
+<p>
+The standard symbol table of ASCIIMathML.js does not contain many symbols.
+It can be extended by adding additional symbols on any webpage that 
+requires them. This is done by adding a few lines of JavaScript code.
+
+</p>
+
+<p>
+For example, suppose we want to add symbols for "not less or equal" and
+"not greater or equal".
+</p>
+
+<p>
+We first have to find the four-digit hexadecimal Unicode value for
+these symbols by looking them up at, say, <a
+href="http://www.w3.org/TR/MathML2/chapter6.html#chars.entity.tables">http://www.w3.org/TR/MathML2/chapter6.html#chars.entity.tables</a>
+</p>
+
+<p>
+Next we have to decide what input strings we want to associate with these
+symbols, say "!<=" and "!>=".
+</p>
+
+<p>
+Finally we add the following lines to the head or body of our HTML file:
+<pre style="border-style:groove">&lt;script type="text/javascript">
+define("!<=","\u2270")
+define("!>=","\u2271")
+&lt;/script>
+</pre>
+</p>
+
+<p>
+Here we test the modified symbol table: 
+<tt>\`a !<= b !>= c\`</tt> produces `a !<= b !>= c`
+</p>
+
+<p>To add a symbol to the LaTeX commands, use the following alternate syntax:
+<pre style="border-style:groove">&lt;script type="text/javascript">
+newcommand("\\nle","\u2270")
+newcommand("\\nge","\u2271")
+&lt;/script>
+</pre>
+</p>
+
+<p>
+Now 
+<tt>\$a \nle b \nge c\$</tt> produces $a \nle b \nge c$.
+</p>
+
+<hr/>
+<p>
+If you know the numeric entity reference of the symbol you want to use
+on an ASCIIMathML webpage, you can also refer to the symbol directly
+by using that reference. E.g \`&amp;#x2270;\` produces `&#x2270;`.
+If a symbol is only used occasionally, this is certainly the simplest
+way to include it.
+</p>
+</body>
+</html>

+ 38 - 0
main/inc/lib/asciimath/asciimathsample.html

@@ -0,0 +1,38 @@
+<html xmlns:mml="http://www.w3.org/1998/Math/MathML">
+<head>
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+<title>ASCIIMathML sample page</title>
+</head>
+<body>
+
+<h2>ASCIIMathML.js sample page</h2>
+
+<p>
+Use auto-math-recognize mode (amath here x^2 and text is 
+mixed endamath) or surround ASCIIMath formulas 
+with left-quotes: 
+`sum_(i=1)^n i=(n(n+1))/2` or LaTeX formulas with \$-signs 
+$\int_0^{\pi/2} \sin x\,dx=1$.
+</p>
+
+<p>
+And here is a simple graph:
+
+agraph plot(sin(x)) endagraph
+
+followed by a more elaborate graph (try double-clicking it, also 
+while holding down shift or alt)
+
+agraph
+width=300; height=200; xmin=-5; xmax=5; xscl=1;
+plot((x-2)*(x-1)*x*(x+1)*(x+2)/2,-2.5,2.5);
+endagraph
+</p>
+
+<p>
+Note: this page uses a relative link to ASCIIMathML.js, 
+so the script should be in the same folder as this sample file.
+</p>
+
+</body>
+</html>

+ 506 - 0
main/inc/lib/asciimath/asciimathsyntax.html

@@ -0,0 +1,506 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+          "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>ASCIIMathML: Syntax and constants</title>
+<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+<style type="text/css">
+#menu, #title, #subtitle, #author {text-align: center}
+body {font-family: Arial; background-color:beige}
+p,table {font-family: Times}
+</style>
+</head>
+<body>
+
+<div id="menu">
+| <a href="asciimath.html">Home Page</a> |
+<a href="asciimathsyntax.html">Syntax</a> |
+<a href="asciimathdemo.html">Try it</a> |
+<a href="asciimathcalculator.html">Calculator</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/mathml/asciimathdownload.html">Download</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathGraphs.html">Graphs</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathFAQ.html">ASCIIMath FAQ</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathMLSandbox.html">Sandbox</a> |
+<a href="http://mathcs.chapman.edu/~jipsen/math/index.php/ASCIIMathML/ASCIIMathCommentsAndSuggestions.html">Comments</a> |
+</div>
+
+<hr/>
+
+<h2 id="title">
+ASCIIMathML.js (ver 2.0): Syntax and List of Constants
+</h2>
+
+<h4 id="subtitle">
+The main aims of the ASCIIMathML syntax are: -- 1. close to standard
+mathematical notation -- 2. easy to read -- 3. easy to type
+</h4>
+
+<p>
+You can use your favorite editor to write HTML pages that use this
+JavaScript program. If the page is viewed by a browser that does not
+support MathML or JavaScript, the ASCII formulas are still quite
+readable. Most users will not have to read the technicalities on
+this page. If you type
+</p>
+
+<pre>amath x^2 or a_(m n) or a_{m n} or (x+1)/y or sqrtx endamath</pre>
+
+<p>
+you pretty much get what you expect: amath x^2 or a_(m n) or a_{m n} or
+(x+1)/y or sqrtx endamath. The a``math ... enda``math tokens are used to
+start/stop the <b>new auto-math-recognize mode</b>. Of course one can still use
+the \`...\` back-quotes to delimit math formulas explicitly
+(\$...\$ should only be used for LaTeX formulas). 
+The choice of grouping parenthesis is up to you
+(they don't have to match either). If the displayed expression can be
+parsed uniquely without them, they are omitted. Printing the table of
+constant symbols (below) may be helpful (but is not necessary if you
+know the LaTeX equivalents).
+</p>
+
+<p>
+It is hoped that this simple input format for MathML will further
+encourage its use on the web. The remainder of this page gives a fairly
+detailed specification of the ASCII syntax. <b>The expressions described here
+correspond to a wellspecified subset of Presentation MathML and behave
+in a predictable way.</b>
+</p>
+
+<p>
+The syntax is very permissive and does not generate syntax
+errors. This allows mathematically incorrect expressions to be
+displayed, which is important for teaching purposes. It also causes
+less frustration when previewing formulas.
+</p>
+
+<p>
+The parser uses no operator precedence and only respects the grouping
+brackets, subscripts, superscript, fractions and (square) roots. This
+is done for reasons of efficiency and generality. The resulting MathML
+code can quite easily be processed further to ensure additional syntactic
+requirements of any particular application.
+</p>
+
+<p>
+<b>The grammar:</b> Here is a definition of the grammar used to parse
+ASCIIMathML expressions. In the Backus-Naur form given below, the
+letter on the left of the ::= represents a category of symbols that
+could be one of the possible sequences of symbols listed on the right.
+The vertical bar | separates the alternatives.
+</p>
+
+<pre>c ::= [A-z] | numbers | greek letters | other constant symbols (see below)
+u ::= 'sqrt' | 'text' | 'bb' |     other unary symbols for font commands
+b ::= 'frac' | 'root' | 'stackrel' binary symbols
+l ::= ( | [ | { | (: | {:          left brackets
+r ::= ) | ] | } | :) | :}          right brackets
+S ::= c | lEr | uS | bSS | "any"   simple expression
+E ::= SE | S/S |S_S | S^S | S_S^S  expression (fraction, sub-, super-, subsuperscript)
+</pre>
+
+<p>
+<b>The translation rules:</b> Each terminal symbol is translated into
+a corresponding MathML node. The constants are mostly converted to
+their respective Unicode symbols. The other expressions are converted
+as follows:<br/>
+<table>
+<tr><td>l`S`r</td><td>`to`</td><td>&lt;mrow>l`S`r&lt;/mrow> 
+(note that any pair of brackets can be used to delimit subexpressions, 
+they don't have to match)</td></tr>
+<tr><td>sqrt `S`</td><td>`to`</td><td>&lt;msqrt>`S'`&lt;/msqrt></td></tr>
+
+<tr><td>text `S`</td><td>`to`</td><td>&lt;mtext>`S'`&lt;/mtext></td></tr>
+<tr><td>"any"</td><td>`to`</td><td>&lt;mtext>any&lt;/mtext></td></tr>
+<tr><td>
+frac `S_1` `S_2`</td><td>`to`</td><td>&lt;mfrac>`S_1'` `S_2'`&lt;/mfrac>
+</td></tr>
+<tr><td>
+
+root `S_1` `S_2`</td><td>`to`</td><td>&lt;mroot>`S_2'` `S_1'`&lt;/mroot>
+</td></tr>
+<tr><td>
+stackrel `S_1` `S_2`</td><td>`to`</td><td>&lt;mover>`S_2'` `S_1'`&lt;/mover>
+</td></tr>
+<tr><td>
+`S_1`/`S_2`</td><td>`to`</td><td>&lt;mfrac>`S_1'` `S_2'`&lt;/mfrac>
+</td></tr>
+
+<tr><td>
+`S_1`_`S_2`</td><td>`to`</td><td>&lt;msub>`S_1` `S_2'`&lt;/msub>
+</td></tr>
+<tr><td>
+`S_1`^`S_2`</td><td>`to`</td><td>&lt;msup>`S_1` `S_2'`&lt;/msup>
+</td></tr>
+<tr><td>
+`S_1`_`S_2`^`S_3`</td><td>`to`</td>
+<td>&lt;msubsup>`S_1` `S_2'` `S_3'`&lt;/msubsup> or
+
+&lt;munderover>`S_1` `S_2'` `S_3'`&lt;/munderover> (in some cases)
+</td></tr>
+</table>
+In the rules above, the expression `S'` is the same as `S`, except that if
+`S` has an outer level of brackets, then `S'` is the expression inside 
+these brackets.
+
+<p>
+<b>Matrices:</b> A simple syntax for matrices is also recognized:
+<br/>
+<tt>l(`S_(11)`,...,`S_(1n)`),(...),(`S_(m1)`,...,`S_(mn)`)r</tt>
+&#x00A0; &#x00A0; or &#x00A0; &#x00A0;
+
+<tt>l[`S_(11)`,...,`S_(1n)`],[...],[`S_(m1)`,...,`S_(mn)`]r</tt>.
+<br/>
+
+Here <tt>l</tt> and <tt>r</tt> stand for any of the left and right
+brackets (just like in the grammar they do not have to match). Both of
+these expressions are translated to
+<br/>
+
+&lt;mrow>l&lt;mtable>&lt;mtr>&lt;mtd>`S_(11)`&lt;/mtd>...
+
+&lt;mtd>`S_(1n)`&lt;/mtd>&lt;/mtr>...
+&lt;mtr>&lt;mtd>`S_(m1)`&lt;/mtd>... 
+&lt;mtd>`S_(mn)`&lt;/mtd>&lt;/mtr>&lt;/mtable>r&lt;/mrow>.
+<br/>
+
+For example 
+<tt>{(S_(11),...,S_(1n)),(vdots,ddots,vdots),(S_(m1),...,S_(mn))]</tt>
+displays as `{(S_(11),...,S_(1n)),(vdots,ddots,vdots),(S_(m1),...,S_(mn))]`.
+
+<br/>
+
+Note that each row must have the same number of expressions, and there
+should be at least two rows.
+
+<p>
+<b>Tokenization:</b> The input formula is broken into tokens using a
+"longest matching initial substring search". Suppose the input formula
+has been processed from left to right up to a fixed position. The
+longest string from the list of constants (given below) that matches
+the initial part of the remainder of the formula is the next token. If
+there is no matching string, then the first character of the remainder
+is the next token. The symbol table at the top of the ASCIIMathML.js
+script specifies whether a symbol is a math operator (surrounded by a
+&lt;mo> tag) or a math identifier (surrounded by a &lt;mi> tag). For
+single character tokens, letters are treated as math identifiers, and
+non-alphanumeric characters are treated as math operators. For digits,
+see "Numbers" below.
+
+<p>
+Spaces are significant when they separate characters and thus prevent
+a certain string of characters from matching one of the
+constants. Multiple spaces and end-of-line characters are equivalent
+to a single space.
+</p>
+
+<h4>
+Now for a complete list of constants (<a
+href="http://math.chapman.edu/cgi-bin/mathxml.pl?Complete_list_of_LaTeX_constants">standard
+LaTeX names</a> also work):
+
+</h4> 
+
+<p>
+Numbers: A string of digits, optionally preceded by a minus sign, and
+optionally followed by a decimal point (a period) and another string
+of digits, is parsed as a single token and converted to a MathML
+number, i.e., enclosed with the &lt;mn> tag. If it is not desirable to 
+have a preceding minus sign be part of the number, a space should be inserted.
+Thus <tt>x-1</tt> is converted to &lt;mi>x&lt;/mi>&lt;mn>-1&lt;/mn>, whereas
+<tt>x - 1</tt> is converted to &lt;mi>x&lt;/mi>&lt;mo>-&lt;/mo>&lt;mn>1&lt;/mn>.
+
+</p>
+
+<p>
+Greek letters:
+alpha `alpha`
+beta `beta`
+chi `chi`
+delta `delta`
+Delta `Delta`
+epsilon `epsilon`
+varepsilon `varepsilon`
+eta `eta`
+gamma `gamma`
+Gamma `Gamma`
+iota `iota`
+kappa `kappa`
+lambda `lambda`
+Lambda `Lambda`
+mu `mu`
+nu `nu`
+omega `omega`
+Omega `Omega`
+phi `phi`
+varphi `varphi`
+Phi `Phi`
+pi `pi`
+Pi `Pi`
+psi `psi`
+Psi `Psi`
+rho `rho`
+sigma `sigma`
+Sigma `Sigma`
+tau `tau`
+theta `theta`
+vartheta `vartheta`
+Theta `Theta`
+upsilon `upsilon`
+xi `xi`
+Xi `Xi`
+zeta `zeta`
+</p>
+
+<table border="5" cellpadding="10">
+<tr valign="top"><td>
+Operation symbols
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>+</td><td>`+`</td></tr>
+<tr><td>-</td><td>`-`</td></tr>
+
+<tr><td>*</td><td>`*`</td></tr>
+<tr><td>**</td><td>`**`</td></tr>
+<tr><td>//</td><td>`//`</td></tr>
+<tr><td>\\</td><td>`\\ `</td></tr>
+<tr><td>xx</td><td>`xx`</td></tr>
+<tr><td>-:</td><td>`-:`</td></tr>
+
+<tr><td>@</td><td>`@`</td></tr>
+<tr><td>o+</td><td>`o+`</td></tr>
+<tr><td>ox</td><td>`ox`</td></tr>
+<tr><td>o.</td><td>`o.`</td></tr>
+<tr><td>sum</td><td>`sum`</td></tr>
+<tr><td>prod</td><td>`prod`</td></tr>
+
+<tr><td>^^</td><td>`^^`</td></tr>
+<tr><td>^^^</td><td>`^^^`</td></tr>
+<tr><td>vv</td><td>`vv`</td></tr>
+<tr><td>vvv</td><td>`vvv`</td></tr>
+<tr><td>nn</td><td>`nn`</td></tr>
+<tr><td>nnn</td><td>`nnn`</td></tr>
+
+<tr><td>uu</td><td>`uu`</td></tr>
+<tr><td>uuu</td><td>`uuu`</td></tr>
+</table>
+</td><td>
+Relation symbols
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>=</td><td>`=`</td></tr>
+<tr><td>!=</td><td>`!=`</td></tr>
+
+<tr><td>< </td><td>`<`</td></tr>
+<tr><td>></td><td>`>`</td></tr>
+<tr><td><=</td><td>`<=`</td></tr>
+<tr><td>>=</td><td>`>=`</td></tr>
+<tr><td>-<</td><td>`-<`</td></tr>
+
+<tr><td>>-</td><td>`>-`</td></tr>
+<tr><td>in</td><td>`in`</td></tr>
+<tr><td>!in</td><td>`notin`</td></tr>
+<tr><td>sub</td><td>`sub`</td></tr>
+<tr><td>sup</td><td>`sup`</td></tr>
+<tr><td>sube</td><td>`sube`</td></tr>
+
+<tr><td>supe</td><td>`supe`</td></tr>
+<tr><td>-=</td><td>`-=`</td></tr>
+<tr><td>~=</td><td>`~=`</td></tr>
+<tr><td>~~</td><td>`~~`</td></tr>
+<tr><td>prop</td><td>`prop`</td></tr>
+</table>
+</td><td>
+
+Logical symbols
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>and</td><td>`and`</td></tr>
+<tr><td>or</td><td>`or`</td></tr>
+<tr><td>not</td><td>`not`</td></tr>
+<tr><td>=></td><td>`=>`</td></tr>
+
+<tr><td>if</td><td>`if`</td></tr>
+<tr><td>iff</td><td>`iff`</td></tr>
+<tr><td>AA</td><td>`AA`</td></tr>
+<tr><td>EE</td><td>`EE`</td></tr>
+<tr><td>_|_</td><td>`_|_`</td></tr>
+<tr><td>TT</td><td>`TT`</td></tr>
+
+<tr><td>|--</td><td>`|--`</td></tr>
+<tr><td>|==</td><td>`|==`</td></tr>
+</table>
+<p>
+Grouping brackets
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>(</td><td>`(`</td></tr>
+<tr><td>)</td><td>`)`</td></tr>
+
+<tr><td>[</td><td>`[`</td></tr>
+<tr><td>]</td><td>`]`</td></tr>
+<tr><td>{</td><td>`{`</td></tr>
+<tr><td>}</td><td>`}`</td></tr>
+<tr><td>(:</td><td>`(:`</td></tr>
+<tr><td>:)</td><td>`:)`</td></tr>
+
+<tr><td>{:</td><td>`{:`</td></tr>
+<tr><td>:}</td><td>`{::}`</td></tr>
+</table>
+
+</td><td>
+Miscellaneous symbols
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>int</td><td>`int`</td></tr>
+
+<tr><td>oint</td><td>`oint`</td></tr>
+<tr><td>del</td><td>`del`</td></tr>
+<tr><td>grad</td><td>`grad`</td></tr>
+<tr><td>+-</td><td>`+-`</td></tr>
+<tr><td>O/</td><td>`O/`</td></tr>
+<tr><td>oo</td><td>`oo`</td></tr>
+
+<tr><td>aleph</td><td>`aleph`</td></tr>
+<tr><td>/_</td><td>`/_`</td></tr>
+<tr><td>:.</td><td>`:.`</td></tr>
+<tr><td>|...|</td><td>|`...`|</td></tr>
+<tr><td>|cdots|</td><td>|`cdots`|</td></tr>
+<tr><td>vdots</td><td>`vdots`</td></tr>
+
+<tr><td>ddots</td><td>`ddots`</td></tr>
+<tr><td>|\ |</td><td>|`\ `|</td></tr>
+<tr><td>|quad|</td><td>|`quad`|</td></tr>
+<tr><td>diamond</td><td>`diamond`</td></tr>
+<tr><td>square</td><td>`square`</td></tr>
+<tr><td>|__</td><td>`|__`</td></tr>
+
+<tr><td>__|</td><td>`__|`</td></tr>
+<tr><td>|~</td><td>`|~`</td></tr>
+<tr><td>~|</td><td>`~|`</td></tr>
+<tr><td>CC</td><td>`CC`</td></tr>
+<tr><td>NN</td><td>`NN`</td></tr>
+<tr><td>QQ</td><td>`QQ`</td></tr>
+
+<tr><td>RR</td><td>`RR`</td></tr>
+<tr><td>ZZ</td><td>`ZZ`</td></tr>
+</table>
+</td><td>
+Standard functions
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>sin</td><td>`sin`</td></tr>
+<tr><td>cos</td><td>`cos`</td></tr>
+
+<tr><td>tan</td><td>`tan`</td></tr>
+<tr><td>csc</td><td>`csc`</td></tr>
+<tr><td>sec</td><td>`sec`</td></tr>
+<tr><td>cot</td><td>`cot`</td></tr>
+<tr><td>sinh</td><td>`sinh`</td></tr>
+<tr><td>cosh</td><td>`cosh`</td></tr>
+
+<tr><td>tanh</td><td>`tanh`</td></tr>
+<tr><td>log</td><td>`log`</td></tr>
+<tr><td>ln</td><td>`ln`</td></tr>
+<tr><td>det</td><td>`det`</td></tr>
+<tr><td>dim</td><td>`dim`</td></tr>
+<tr><td>lim</td><td>`lim`</td></tr>
+
+<tr><td>mod</td><td>`mod`</td></tr>
+<tr><td>gcd</td><td>`gcd`</td></tr>
+<tr><td>lcm</td><td>`lcm`</td></tr>
+<tr><td>min</td><td>`min`</td></tr>
+<tr><td>max</td><td>`max`</td></tr>
+</table>
+<p>
+
+Accents
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>hat x</td><td>`hat x`</td></tr>
+<tr><td>bar x</td><td>`bar x`</td></tr>
+<tr><td>ul x</td><td>`ul x`</td></tr>
+<tr><td>vec x</td><td>`vec x`</td></tr>
+
+<tr><td>dot x</td><td>`dot x`</td></tr>
+<tr><td>ddot x</td><td>`ddot x`</td></tr>
+</table>
+
+</td><td>
+Arrows
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>uarr</td><td>`uarr`</td></tr>
+
+<tr><td>darr</td><td>`darr`</td></tr>
+<tr><td>rarr</td><td>`rarr`</td></tr>
+<tr><td>-></td><td>`->`</td></tr>
+<tr><td>|-></td><td>`|->`</td></tr>
+<tr><td>larr</td><td>`larr`</td></tr>
+<tr><td>harr</td><td>`harr`</td></tr>
+
+<tr><td>rArr</td><td>`rArr`</td></tr>
+<tr><td>lArr</td><td>`lArr`</td></tr>
+<tr><td>hArr</td><td>`hArr`</td></tr>
+</table>
+<p>
+Font commands
+<table border="5" cellpadding="10">
+<tr><th>Type</th><th>See</th></tr>
+<tr><td>bb A</td><td>`bb A`</td></tr>
+
+<tr><td>bbb A</td><td>`bbb A`</td></tr>
+<tr><td>cc A</td><td>`cc A`</td></tr>
+<tr><td>tt A</td><td>`tt A`</td></tr>
+<tr><td>fr A</td><td>`fr A`</td></tr>
+<tr><td>sf A</td><td>`sf A`</td></tr>
+</table>
+
+</td></tr>
+</table>
+
+<p>
+Of course you may want or need other symbols from the thousands of <a
+href="http://www.ctan.org/tex-archive/info/symbols/comprehensive/symbols-letter.pdf">LaTeX
+symbols</a> or <a
+href="http://www.alanwood.net/unicode/#links">unicode
+symbols</a>. Fortunately ASCIIMathML.js is very <a
+href="asciimathextend.html">easy
+to extend</a>, so you can tailor it to your specific needs. (This
+could be compared to the LaTeX macro files that many users have
+developed over the years.)
+</p>
+
+<!--p>
+Large files with many formulas can take quite some time to display,
+especially on older hardware. To address this problem, there is a
+version ASCIIMathMLite.js that has a shorter symbol table (without the
+LaTeX symbol names) and slightly simplified parser. Send me an email
+at <a href="mailto:jipsen@chapman.edu">jipsen@chapman.edu</a> if you
+would like a copy.
+</p>
+
+<p>
+Another version that also recognizes some <a
+href="http://www.latex-project.org/">LaTeX</a> layout commands and
+(the fairly standard) <a
+href="http://en.wikipedia.org/wiki/Wikipedia:How_to_edit_a_page">Wiki
+formatting codes</a> for ASCII text is in the works. This further
+simplifies producing mathematical content for the web. However such a
+development is less easily justified since there are good free HTML
+editors and the HTML syntax is a well-established standard that is
+simple enough to be coded by hand.
+</p-->
+
+<hr/>
+
+<div id="author">
+<a href="http://www.chapman.edu/~jipsen/">Peter Jipsen</a>, 
+<a href="http://www.chapman.edu/">Chapman University</a>, September 2007
+
+<a href="http://validator.w3.org/check/referer"><img border="0"
+src="http://www.w3.org/Icons/valid-html401"
+alt="Valid HTML 4.01!" height="31" width="88"></a>
+</div>
+</body>
+</html>

+ 8 - 0
main/inc/lib/asciimath/d.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" 
+  "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+<svg id="root" xml:space="preserve" width="100%" height="100%" 
+  preserveAspectRatio="xMidYMid meet"
+  xmlns="http://www.w3.org/2000/svg"
+  xmlns:xlink="http:///www.w3.org/1999/xlink">
+</svg>

+ 44 - 0
main/inc/lib/asciimath/filter.php

@@ -0,0 +1,44 @@
+<?PHP
+/////////////////////////////////////////////////////////////////////////////
+//                                                                         //
+// NOTICE OF COPYRIGHT                                                     //
+//                                                                         //
+// Moodle - Filter for converting asciimath notation to MathML             //
+//                                                                         //
+// Copyright (C) 2007 by Peter Jipsen                                      //
+// This program is free software; you can redistribute it and/or modify    //
+// it under the terms of the GNU General Public License as published by    //
+// the Free Software Foundation; either version 2 of the License, or       //
+// (at your option) any later version.                                     //
+//                                                                         //
+// This program is distributed in the hope that it will be useful,         //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of          //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
+// GNU General Public License for more details:                            //
+//                                                                         //
+//          http://www.gnu.org/copyleft/gpl.html                           //
+//                                                                         //
+/////////////////////////////////////////////////////////////////////////////
+//-------------------------------------------------------------------------
+// NOTE: This Moodle text filter uses javascript to process ASCIIMath commands
+// embedded in the text.  Math should be surrounded by `...` or $...$
+// or put    amath ... amathoff   around the whole text to use the
+// experimental auto-math-recognize mode.
+//
+// The filter enables the ASCIIMathML.js code to do most of the work. 
+//
+// A copy of ASCIIMathML (version 2.0 or later) is included and
+// automatically loaded in the file asciimath/javascript.php
+//
+//-------------------------------------------------------------------------
+
+$textfilter_function='asciimath_filter';
+if (function_exists($textfilter_function)) {return;}
+
+function asciimath_filter ($courseid, $text) {
+  global $CFG;
+  $text = '<span id="processasciimathinmoodle" class="'.$CFG->wwwroot.'/filter/asciimath/"></span>'.$text;
+  return $text;
+}
+
+?>

+ 8 - 0
main/inc/lib/asciimath/index.html

@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+</head>
+<body>
+<br />
+</body>
+</html>

+ 28 - 0
main/inc/lib/asciimath/javascript.php

@@ -0,0 +1,28 @@
+/////////////////////////////////////////////////////////////////////////////
+//                                                                         //
+// NOTICE OF COPYRIGHT                                                     //
+//                                                                         //
+// Moodle - Filter for converting ASCIImath notation to MathML             //
+// Now also handles a larger subset of LaTeX, as well as ASCIIsvg          //
+//                                                                         //
+// Copyright (C) 2007 by Peter Jipsen                                      //
+// This program is free software; you can redistribute it and/or modify    //
+// it under the terms of the GNU General Public License as published by    //
+// the Free Software Foundation; either version 2 of the License, or       //
+// (at your option) any later version.                                     //
+//                                                                         //
+// This program is distributed in the hope that it will be useful,         //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of          //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           //
+// GNU General Public License for more details:                            //
+//                                                                         //
+//          http://www.gnu.org/copyleft/gpl.html                           //
+//                                                                         //
+/////////////////////////////////////////////////////////////////////////////
+
+// if this script url sniffing does not work try setting wwwroot explicitly
+// var wwwroot = "http://path/to/your/moodledir"
+// or copy the ASCIIMathML.js file into this file.
+
+var wwwroot = document.getElementsByTagName("script")[0].src.replace(/((.*?)\/lib\/.*)/,"$2"); 
+document.write('<script src="'+wwwroot+'/filter/asciimath/ASCIIMathML.js"></script>');

+ 37 - 0
main/inc/lib/asciimath/readme.txt

@@ -0,0 +1,37 @@
+ASCIIMathML.js 
+
+Brief Instructions (2007-9-28)
+
+This script can be used in any html page and also in systems like Moodle.
+The license is LGPL (see top of ASCIIMathML.js for more info).
+
+In a html page, just add the following line near the top of your file:
+<script type="text/javascript" src="ASCIIMathML.js"></script>
+
+To install in Moodle, just move this asciimath-x.y.z folder into moodle/filter,
+rename the folder "asciimath" and go to the admin panel Modules->Filters 
+to switch it on.
+
+Then try some ASCIIMath on your webpages: `x/y` 
+
+or LaTeX $\sqrt{x}$ and $$\int_0^1 x^2 dx$$ (only a \emph{subset} works, 
+including a few environments like \begin{theorem}... and \begin{proof})
+
+Try some graphics like agraph plot(sin(x)) endagraph or 
+\begin{graph}plot(sin(x))\end{graph}
+
+Try the auto-math-recognize mode: amath here we can mix x^2 and text endamath
+
+All this is supposed to work in Firefox on many platforms (recommended; 
+you may be asked to install math fonts) and in Internet Explorer (only 
+on WinXP and you have to install MathPlayer and Adobe SVGview).
+
+For more examples, see http://www.chapman.edu/~jipsen/asciimath.html and
+http://mathcs.chapman.edu/~jipsen/math
+
+If you use this script on the web, please send an email to jipsen@chapman.edu
+and put a link to http://www.chapman.edu/~jipsen/asciimath.html on your page.
+
+Best wishes with ASCIIMathML.js
+
+Peter Jipsen

+ 3 - 2
main/inc/lib/blog.lib.php

@@ -3026,11 +3026,12 @@ function get_blog_post_from_user($course_db_name, $user_id) {
 				ORDER BY post.date_creation DESC ";
 		$result = api_sql_query($sql, __FILE__, __LINE__);
 		$return_data = '';
-		$my_course_info=explode('_',$course_db_name);
+		//$my_course_info=explode('_',$course_db_name);
+		$my_course_id=CourseManager::get_course_id_by_database_name($course_db_name);	
 		if (Database::num_rows($result)!=0) {
 			while ($row=Database::fetch_array($result)) {
 				$return_data.=  '<div class="clear"></div><br />';
-	 			$return_data.=  '<div class="actions" style="margin-left:5px;margin-right:5px;">'.$row['title'].'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div style="float:right;margin-top:-18px"><a href="../blog/blog.php?blog_id='.$row['blog_id'].'&gidReq=&cidReq='.$my_course_info[1].' " >'.get_lang('SeeBlog').'</a></div></div>';
+	 			$return_data.=  '<div class="actions" style="margin-left:5px;margin-right:5px;"><img src="../img/blog.gif" />'.$row['title'].'&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<div style="float:right;margin-top:-18px"><a href="../blog/blog.php?blog_id='.$row['blog_id'].'&gidReq=&cidReq='.$my_course_id.' " >'.get_lang('SeeBlog').'</a></div></div>';
 	 			$return_data.=  '<br / >';
 				//$return_data.= '<strong>'.$row['title'].'</strong>'; echo '<br>';
 				$return_data.= $row['full_text'];

+ 29 - 4
main/inc/lib/course.lib.php

@@ -1895,18 +1895,32 @@ class CourseManager {
     /**
      * Get list of courses for a given user
      * @param int       user ID
+     * @param boolean   Whether to include courses from session or not
      * @return array    List of codes and db names
      * @author isaac flores paz
      */
-	public static function get_courses_list_by_user_id ($user_id) {
+	public static function get_courses_list_by_user_id ($user_id, $include_sessions=false) {
 		$course_list=array();
+        $codes = array();
+        $user_id = intval($user_id);
 		$tbl_course			 = Database::get_main_table(TABLE_MAIN_COURSE);
 		$tbl_course_rel_user = Database::get_main_table(TABLE_MAIN_COURSE_USER);
-		$sql='SELECT c.code,c.db_name,c.title FROM '.$tbl_course.' c inner join '.$tbl_course_rel_user.' cru on c.code=cru.course_code  WHERE cru.user_id='.Database::escape_string($user_id);
+		$sql='SELECT c.code,c.db_name,c.title FROM '.$tbl_course.' c inner join '.$tbl_course_rel_user.' cru on c.code=cru.course_code  WHERE cru.user_id='.$user_id;
 		$result=api_sql_query($sql,__FILE__,__LINE__);
 		while ($row=Database::fetch_array($result,'ASSOC')) {
-			$course_list[]=$row;			
-		}
+			$course_list[]=$row;
+            $codes[] = $row['code'];
+		}
+        if ($include_sessions === true) {
+            $tbl_csu = Database::get_main_table(TABLE_MAIN_SESSION_COURSE_USER);
+            $s = "SELECT distinct(c.code),c.db_name,c.title FROM $tbl_csu s, $tbl_course c WHERE id_user = $user_id AND s.course_code=c.code";
+        	$r = Database::query($s,__FILE__,__LINE__);
+            while ($row=Database::fetch_array($r,'ASSOC')) {
+                if (!in_array($row['code'],$codes)) {
+                    $course_list[]=$row;
+                }
+            }
+        }
 		return $course_list;
 	}
     /**
@@ -2115,5 +2129,16 @@ class CourseManager {
 		} else {
 			return false; //field not found
 		}
+	}
+	/**
+	 * Get the course id of an course by the database name
+	 * @param string The database name
+	 * @return string The course id
+	 */
+	public static function get_course_id_by_database_name ($db_name) {
+	   $t_course = Database::get_main_table(TABLE_MAIN_COURSE);	
+	   $sql='SELECT code FROM '.$t_course.' WHERE db_name="'.Database::escape_string($db_name).'"';
+	   $rs=Database::query($sql,__FILE__,__LINE__);
+	   return Database::result($rs,0,'code');
 	}	
 } //end class CourseManager

+ 21 - 38
main/inc/lib/events.lib.inc.php

@@ -105,7 +105,6 @@ function event_login()
 				(login_user_id,
 				 login_ip,
 				 login_date)
-
 				 VALUES
 					('".$_user['user_id']."',
 					'".Database::escape_string($_SERVER['REMOTE_ADDR'])."',
@@ -135,28 +134,23 @@ function event_access_course()
 	if(api_get_setting('use_session_mode')=='true' && isset($_SESSION['id_session']))
 	{
 		$id_session = intval($_SESSION['id_session']);
-	}
+	} 
 	else
 	{
 		$id_session = 0;
 	}
 
 	$reallyNow = time();
-	if ($_user['user_id'])
-	{
+	if ($_user['user_id']) {
 		$user_id = "'".$_user['user_id']."'";
-	}
-	else // anonymous
-		{
-		$user_id = "NULL";
+	} else {
+		$user_id = "0"; // no one
 	}
 	$sql = "INSERT INTO ".$TABLETRACK_ACCESS."
 				(access_user_id,
 				 access_cours_code,
 				 access_date)
-
 				VALUES
-
 				(".$user_id.",
 				'".$_cid."',
 				FROM_UNIXTIME(".$reallyNow."))";
@@ -214,7 +208,7 @@ function event_access_tool($tool, $id_session=0)
 	}
 
 	$reallyNow = time();
-	$user_id = $_user['user_id'] ? "'".$_user['user_id']."'" : "NULL"; // "NULL" is anonymous
+	$user_id = $_user['user_id'] ? "'".$_user['user_id']."'" : "0"; // no one
 	// record information
 	// only if user comes from the course $_cid
 	//if( eregi($_configuration['root_web'].$_cid,$_SERVER['HTTP_REFERER'] ) )
@@ -230,9 +224,7 @@ function event_access_tool($tool, $id_session=0)
 							 access_cours_code,
 							 access_tool,
 							 access_date)
-
 							VALUES
-
 							(".$user_id.",".// Don't add ' ' around value, it's already done.
 					"'".$_cid."' ,
 					'".htmlspecialchars($tool, ENT_QUOTES)."',
@@ -285,10 +277,8 @@ function event_download($doc_url)
 	if ($_user['user_id'])
 	{
 		$user_id = "'".$_user['user_id']."'";
-	}
-	else // anonymous
-		{
-		$user_id = "NULL";
+	} else {
+		$user_id = "0";
 	}
 	$sql = "INSERT INTO ".$TABLETRACK_DOWNLOADS."
 				(
@@ -323,30 +313,23 @@ function event_upload($doc_id)
 	global $_cid;
 	global $TABLETRACK_UPLOADS;
 	// if tracking is disabled record nothing
-	if (!$_configuration['tracking_enabled'])
-	{
+	if (!$_configuration['tracking_enabled']) {
 		return 0;
 	}
 
 	$reallyNow = time();
-	if ($_user['user_id'])
-	{
+	if (isset($_user['user_id']) && $_user['user_id']!='') {
 		$user_id = "'".$_user['user_id']."'";
-	}
-	else // anonymous
-		{
-		$user_id = "NULL";
+	} else {
+		$user_id = "0"; // anonymous
 	}
 	$sql = "INSERT INTO ".$TABLETRACK_UPLOADS."
-				(
-				 upload_user_id,
-				 upload_cours_id,
-				 upload_work_id,
-				 upload_date
+				( upload_user_id,
+				  upload_cours_id,
+				  upload_work_id,
+				  upload_date
 				)
-
-				VALUES
-				(
+				VALUES (
 				 ".$user_id.",
 				 '".$_cid."',
 				 '".$doc_id."',
@@ -375,11 +358,11 @@ function event_link($link_id)
 	}
 
 	$reallyNow = time();
-	if ($_user['user_id']) {
+	if (isset($_user['user_id']) && $_user['user_id']!='') {
 		$user_id = "'".Database::escape_string($_user['user_id'])."'";
 	} else {
 		// anonymous
-		$user_id = "NULL";
+		$user_id = "0";
 	}
 	
 	$sql = "INSERT INTO ".$TABLETRACK_LINKS."
@@ -445,11 +428,11 @@ function create_event_exercice($exo_id)
 	global $_user, $_cid, $_configuration;
 	$TABLETRACK_EXERCICES = Database::get_statistic_table(TABLE_STATISTIC_TRACK_E_EXERCICES);
 	$reallyNow = time();
-	if ($_user['user_id']) {
+	if (isset($_user['user_id']) && $_user['user_id']!='') {
 		$user_id = "'".$_user['user_id']."'";
 	} else {
 		// anonymous
-		$user_id = "NULL";
+		$user_id = "0";
 	}
 
 	if(defined('ENABLED_LIVE_EXERCISE_TRACKING')){
@@ -500,7 +483,7 @@ function exercise_attempt($score,$answer,$quesId,$exeId,$j)
 	}
 
 	$reallyNow = time();
-	if ($_user['user_id'])
+	if (isset($_user['user_id']) && $_user['user_id']!='')
 	{
 		$user_id = "'".$_user['user_id']."'";
 	}

+ 2 - 2
main/inc/lib/fckeditor/editor/_source/commandclasses/fck_othercommands.js

@@ -40,7 +40,7 @@ var FCKDialogCommand = function( name, title, url, width, height, getStateFuncti
 
 FCKDialogCommand.prototype.Execute = function()
 {
-	FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, this.CustomValue, null, this.Resizable ) ;
+	FCKDialog.OpenDialog( 'FCKDialog_' + this.Name , this.Title, this.Url, this.Width, this.Height, this.CustomValue, this.Resizable ) ;
 }
 
 FCKDialogCommand.prototype.GetState = function()
@@ -186,7 +186,7 @@ FCKSourceCommand.prototype.Execute = function()
 	{
 		var iWidth	= FCKConfig.ScreenWidth * 0.65 ;
 		var iHeight	= FCKConfig.ScreenHeight * 0.65 ;
-		FCKDialog.OpenDialog( 'FCKDialog_Source', FCKLang.Source, 'dialog/fck_source.html', iWidth, iHeight, null, null, true ) ;
+		FCKDialog.OpenDialog( 'FCKDialog_Source', FCKLang.Source, 'dialog/fck_source.html', iWidth, iHeight, null, true ) ;
 	}
 	else
 	    FCK.SwitchEditMode() ;

+ 4 - 4
main/inc/lib/fckeditor/editor/_source/commandclasses/fcktextcolorcommand.js

@@ -193,9 +193,9 @@ FCKTextColorCommand.prototype._CreatePanelBody = function( targetDocument, targe
 		oDiv.innerHTML = '<table width="100%" cellpadding="0" cellspacing="0" border="0"><tr><td nowrap align="center">' + FCKLang.ColorMoreColors + '</td></tr></table>' ;
 
 		FCKTools.AddEventListenerEx( oDiv, 'click', FCKTextColorCommand_MoreOnClick, this ) ;
+	
+		// Dirty hack for Opera, Safari and Firefox 3.
+		if ( !FCKBrowserInfo.IsIE )
+			oDiv.style.width = '96%' ;
 	}
-
-	// Dirty hack for Opera, Safari and Firefox 3.
-	if ( !FCKBrowserInfo.IsIE )
-		oDiv.style.width = '96%' ;
 }

+ 178 - 178
main/inc/lib/fckeditor/editor/_source/fckeditorapi.js

@@ -1,179 +1,179 @@
-/*
- * FCKeditor - The text editor for Internet - http://www.fckeditor.net
- * Copyright (C) 2003-2009 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 ==
- *
- * Create the FCKeditorAPI object that is available as a global object in
- * the page where the editor is placed in.
- */
-
-var FCKeditorAPI ;
-
-function InitializeAPI()
-{
-	var oParentWindow = window.parent ;
-
-	if ( !( FCKeditorAPI = oParentWindow.FCKeditorAPI ) )
-	{
-		// Make the FCKeditorAPI object available in the parent window. Use
-		// eval so this core runs in the parent's scope and so it will still be
-		// available if the editor instance is removed ("Can't execute code
-		// from a freed script" error).
-
-		// Note: we check the existence of oEditor.GetParentForm because some external
-		// code (like JSON) can extend the Object prototype and we get then extra oEditor
-		// objects that aren't really FCKeditor instances.
-		var sScript =
+/*
+ * FCKeditor - The text editor for Internet - http://www.fckeditor.net
+ * Copyright (C) 2003-2009 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 ==
+ *
+ * Create the FCKeditorAPI object that is available as a global object in
+ * the page where the editor is placed in.
+ */
+
+var FCKeditorAPI ;
+
+function InitializeAPI()
+{
+	var oParentWindow = window.parent ;
+
+	if ( !( FCKeditorAPI = oParentWindow.FCKeditorAPI ) )
+	{
+		// Make the FCKeditorAPI object available in the parent window. Use
+		// eval so this core runs in the parent's scope and so it will still be
+		// available if the editor instance is removed ("Can't execute code
+		// from a freed script" error).
+
+		// Note: we check the existence of oEditor.GetParentForm because some external
+		// code (like JSON) can extend the Object prototype and we get then extra oEditor
+		// objects that aren't really FCKeditor instances.
+		var sScript =
 			'window.FCKeditorAPI = {' +
-				'Version : "2.6.4.1",' +
-				'VersionBuild : "23195",' +
-				'Instances : window.FCKeditorAPI && window.FCKeditorAPI.Instances || {},' +
-
-				'GetInstance : function( name )' +
-				'{' +
-					'return this.Instances[ name ];' +
-				'},' +
-
-				'_FormSubmit : function()' +
-				'{' +
-					'for ( var name in FCKeditorAPI.Instances )' +
-					'{' +
-						'var oEditor = FCKeditorAPI.Instances[ name ] ;' +
-						'if ( oEditor.GetParentForm && oEditor.GetParentForm() == this )' +
-							'oEditor.UpdateLinkedField() ;' +
-					'}' +
-					'this._FCKOriginalSubmit() ;' +
-				'},' +
-
-				'_FunctionQueue	: window.FCKeditorAPI && window.FCKeditorAPI._FunctionQueue || {' +
-					'Functions : new Array(),' +
-					'IsRunning : false,' +
-
-					'Add : function( f )' +
-					'{' +
-						'this.Functions.push( f );' +
-						'if ( !this.IsRunning )' +
-							'this.StartNext();' +
-					'},' +
-
-					'StartNext : function()' +
-					'{' +
-						'var aQueue = this.Functions ;' +
-						'if ( aQueue.length > 0 )' +
-						'{' +
-							'this.IsRunning = true;' +
-							'aQueue[0].call();' +
-						'}' +
-						'else ' +
-							'this.IsRunning = false;' +
-					'},' +
-
-					'Remove : function( f )' +
-					'{' +
-						'var aQueue = this.Functions;' +
-						'var i = 0, fFunc;' +
-						'while( (fFunc = aQueue[ i ]) )' +
-						'{' +
-							'if ( fFunc == f )' +
-								'aQueue.splice( i,1 );' +
-							'i++ ;' +
-						'}' +
-						'this.StartNext();' +
-					'}' +
-				'}' +
-			'}' ;
-
-		// In IE, the "eval" function is not always available (it works with
-		// the JavaScript samples, but not with the ASP ones, for example).
-		// So, let's use the execScript instead.
-		if ( oParentWindow.execScript )
-			oParentWindow.execScript( sScript, 'JavaScript' ) ;
-		else
-		{
-			if ( FCKBrowserInfo.IsGecko10 )
-			{
-				// FF 1.0.4 gives an error with the request bellow. The
-				// following seams to work well.
-				eval.call( oParentWindow, sScript ) ;
-			}
-			else if( FCKBrowserInfo.IsAIR )
-			{
-				FCKAdobeAIR.FCKeditorAPI_Evaluate( oParentWindow, sScript ) ;
-			}
-			else if ( FCKBrowserInfo.IsSafari )
-			{
-				// oParentWindow.eval in Safari executes in the calling window
-				// environment, instead of the parent one. The following should
-				// make it work.
-				var oParentDocument = oParentWindow.document ;
-				var eScript = oParentDocument.createElement('script') ;
-				eScript.appendChild( oParentDocument.createTextNode( sScript ) ) ;
-				oParentDocument.documentElement.appendChild( eScript ) ;
-			}
-			else
-				oParentWindow.eval( sScript ) ;
-		}
-
-		FCKeditorAPI = oParentWindow.FCKeditorAPI ;
-
-		// The __Instances properly has been changed to the public Instances,
-		// but we should still have the "deprecated" version of it.
-		FCKeditorAPI.__Instances = FCKeditorAPI.Instances ;
-	}
-
-	// Add the current instance to the FCKeditorAPI's instances collection.
-	FCKeditorAPI.Instances[ FCK.Name ] = FCK ;
-}
-
-// Attach to the form onsubmit event and to the form.submit().
-function _AttachFormSubmitToAPI()
-{
-	// Get the linked field form.
-	var oForm = FCK.GetParentForm() ;
-
-	if ( oForm )
-	{
-		// Attach to the onsubmit event.
-		FCKTools.AddEventListener( oForm, 'submit', FCK.UpdateLinkedField ) ;
-
-		// IE sees oForm.submit function as an 'object'.
-		if ( !oForm._FCKOriginalSubmit && ( typeof( oForm.submit ) == 'function' || ( !oForm.submit.tagName && !oForm.submit.length ) ) )
-		{
-			// Save the original submit.
-			oForm._FCKOriginalSubmit = oForm.submit ;
-
-			// Create our replacement for the submit.
-			oForm.submit = FCKeditorAPI._FormSubmit ;
-		}
-	}
-}
-
-function FCKeditorAPI_Cleanup()
-{
-	if ( window.FCKConfig && FCKConfig.MsWebBrowserControlCompat
-			&& !window.FCKUnloadFlag )
-		return ;
-	delete FCKeditorAPI.Instances[ FCK.Name ] ;
-}
-function FCKeditorAPI_ConfirmCleanup()
-{
-	if ( window.FCKConfig && FCKConfig.MsWebBrowserControlCompat )
-		window.FCKUnloadFlag = true ;
-}
-FCKTools.AddEventListener( window, 'unload', FCKeditorAPI_Cleanup ) ;
-FCKTools.AddEventListener( window, 'beforeunload', FCKeditorAPI_ConfirmCleanup) ;
+				'Version : "2.6.4.1",' +
+				'VersionBuild : "23405",' +
+				'Instances : window.FCKeditorAPI && window.FCKeditorAPI.Instances || {},' +
+
+				'GetInstance : function( name )' +
+				'{' +
+					'return this.Instances[ name ];' +
+				'},' +
+
+				'_FormSubmit : function()' +
+				'{' +
+					'for ( var name in FCKeditorAPI.Instances )' +
+					'{' +
+						'var oEditor = FCKeditorAPI.Instances[ name ] ;' +
+						'if ( oEditor.GetParentForm && oEditor.GetParentForm() == this )' +
+							'oEditor.UpdateLinkedField() ;' +
+					'}' +
+					'this._FCKOriginalSubmit() ;' +
+				'},' +
+
+				'_FunctionQueue	: window.FCKeditorAPI && window.FCKeditorAPI._FunctionQueue || {' +
+					'Functions : new Array(),' +
+					'IsRunning : false,' +
+
+					'Add : function( f )' +
+					'{' +
+						'this.Functions.push( f );' +
+						'if ( !this.IsRunning )' +
+							'this.StartNext();' +
+					'},' +
+
+					'StartNext : function()' +
+					'{' +
+						'var aQueue = this.Functions ;' +
+						'if ( aQueue.length > 0 )' +
+						'{' +
+							'this.IsRunning = true;' +
+							'aQueue[0].call();' +
+						'}' +
+						'else ' +
+							'this.IsRunning = false;' +
+					'},' +
+
+					'Remove : function( f )' +
+					'{' +
+						'var aQueue = this.Functions;' +
+						'var i = 0, fFunc;' +
+						'while( (fFunc = aQueue[ i ]) )' +
+						'{' +
+							'if ( fFunc == f )' +
+								'aQueue.splice( i,1 );' +
+							'i++ ;' +
+						'}' +
+						'this.StartNext();' +
+					'}' +
+				'}' +
+			'}' ;
+
+		// In IE, the "eval" function is not always available (it works with
+		// the JavaScript samples, but not with the ASP ones, for example).
+		// So, let's use the execScript instead.
+		if ( oParentWindow.execScript )
+			oParentWindow.execScript( sScript, 'JavaScript' ) ;
+		else
+		{
+			if ( FCKBrowserInfo.IsGecko10 )
+			{
+				// FF 1.0.4 gives an error with the request bellow. The
+				// following seams to work well.
+				eval.call( oParentWindow, sScript ) ;
+			}
+			else if( FCKBrowserInfo.IsAIR )
+			{
+				FCKAdobeAIR.FCKeditorAPI_Evaluate( oParentWindow, sScript ) ;
+			}
+			else if ( FCKBrowserInfo.IsSafari )
+			{
+				// oParentWindow.eval in Safari executes in the calling window
+				// environment, instead of the parent one. The following should
+				// make it work.
+				var oParentDocument = oParentWindow.document ;
+				var eScript = oParentDocument.createElement('script') ;
+				eScript.appendChild( oParentDocument.createTextNode( sScript ) ) ;
+				oParentDocument.documentElement.appendChild( eScript ) ;
+			}
+			else
+				oParentWindow.eval( sScript ) ;
+		}
+
+		FCKeditorAPI = oParentWindow.FCKeditorAPI ;
+
+		// The __Instances properly has been changed to the public Instances,
+		// but we should still have the "deprecated" version of it.
+		FCKeditorAPI.__Instances = FCKeditorAPI.Instances ;
+	}
+
+	// Add the current instance to the FCKeditorAPI's instances collection.
+	FCKeditorAPI.Instances[ FCK.Name ] = FCK ;
+}
+
+// Attach to the form onsubmit event and to the form.submit().
+function _AttachFormSubmitToAPI()
+{
+	// Get the linked field form.
+	var oForm = FCK.GetParentForm() ;
+
+	if ( oForm )
+	{
+		// Attach to the onsubmit event.
+		FCKTools.AddEventListener( oForm, 'submit', FCK.UpdateLinkedField ) ;
+
+		// IE sees oForm.submit function as an 'object'.
+		if ( !oForm._FCKOriginalSubmit && ( typeof( oForm.submit ) == 'function' || ( !oForm.submit.tagName && !oForm.submit.length ) ) )
+		{
+			// Save the original submit.
+			oForm._FCKOriginalSubmit = oForm.submit ;
+
+			// Create our replacement for the submit.
+			oForm.submit = FCKeditorAPI._FormSubmit ;
+		}
+	}
+}
+
+function FCKeditorAPI_Cleanup()
+{
+	if ( window.FCKConfig && FCKConfig.MsWebBrowserControlCompat
+			&& !window.FCKUnloadFlag )
+		return ;
+	delete FCKeditorAPI.Instances[ FCK.Name ] ;
+}
+function FCKeditorAPI_ConfirmCleanup()
+{
+	if ( window.FCKConfig && FCKConfig.MsWebBrowserControlCompat )
+		window.FCKUnloadFlag = true ;
+}
+FCKTools.AddEventListener( window, 'unload', FCKeditorAPI_Cleanup ) ;
+FCKTools.AddEventListener( window, 'beforeunload', FCKeditorAPI_ConfirmCleanup) ;

+ 32 - 0
main/inc/lib/fckeditor/editor/_source/internals/fck.js

@@ -955,6 +955,38 @@ function _FCK_EditingArea_OnLoad()
 	FCKTools.AddEventListener( FCK.EditorDocument, 'mousemove', _FCK_MouseEventsListener ) ;
 	FCKTools.AddEventListener( FCK.EditorDocument, 'mousedown', _FCK_MouseEventsListener ) ;
 	FCKTools.AddEventListener( FCK.EditorDocument, 'mouseup', _FCK_MouseEventsListener ) ;
+	if ( FCKBrowserInfo.IsSafari )
+	{
+		// #3481: WebKit has a bug with paste where the paste contents may leak
+		// outside table cells. So add padding nodes before and after the paste.
+		FCKTools.AddEventListener( FCK.EditorDocument, 'paste', function( evt )
+		{
+			var range = new FCKDomRange( FCK.EditorWindow );
+			var nodeBefore = FCK.EditorDocument.createTextNode( '\ufeff' );
+			var nodeAfter = FCK.EditorDocument.createElement( 'a' );
+			nodeAfter.id = 'fck_paste_padding';
+			nodeAfter.innerHTML = '&#65279;';
+			range.MoveToSelection();
+			range.DeleteContents();
+
+			// Insert padding nodes.
+			range.InsertNode( nodeBefore );
+			range.Collapse();
+			range.InsertNode( nodeAfter );
+
+			// Move the selection to between the padding nodes.
+			range.MoveToPosition( nodeAfter, 3 );
+			range.Select();
+
+			// Remove the padding nodes after the paste is done.
+			setTimeout( function()
+				{
+					nodeBefore.parentNode.removeChild( nodeBefore );
+					nodeAfter = FCK.EditorDocument.getElementById( 'fck_paste_padding' );
+					nodeAfter.parentNode.removeChild( nodeAfter );
+				}, 0 );
+		} );
+	}
 
 	// Most of the CTRL key combos do not work under Safari for onkeydown and onkeypress (See #1119)
 	// But we can use the keyup event to override some of these...

+ 10 - 0
main/inc/lib/fckeditor/editor/_source/internals/fck_gecko.js

@@ -375,6 +375,16 @@ FCK.InsertHtml = function( html )
 
 		range = new FCKDomRange( this.EditorWindow ) ;
 		range.MoveToSelection() ;
+
+		// If the first element (if exists) of the document fragment is a block
+		// element, then split the current block. (#1537)
+		var currentNode = docFrag.RootNode.firstChild ;
+		while ( currentNode && currentNode.nodeType != 1 )
+			currentNode = currentNode.nextSibling ;
+		
+		if ( currentNode && FCKListsLib.BlockElements[ currentNode.nodeName.toLowerCase() ] )
+			range.SplitBlock() ;
+
 		range.DeleteContents() ;
 		range.InsertNode( docFrag.RootNode ) ;
 

+ 14 - 4
main/inc/lib/fckeditor/editor/_source/internals/fck_ie.js

@@ -172,7 +172,12 @@ FCK.InsertHtml = function( html )
 	oSel.createRange().pasteHTML( html ) ;
 
 	// Remove the fake node
-	FCK.EditorDocument.getElementById('__fakeFCKRemove__').removeNode( true ) ;
+	var fake = FCK.EditorDocument.getElementById('__fakeFCKRemove__') ;
+	// If the span is the only child of a node (so the inserted HTML is beyond that),
+	// remove also that parent that isn't needed. #1537
+	if (fake.parentNode.childNodes.length == 1) 
+		fake = fake.parentNode ;
+	fake.removeNode( true ) ;
 
 	FCKDocumentProcessor.Process( FCK.EditorDocument ) ;
 
@@ -373,22 +378,27 @@ FCK.CreateLink = function( url, noUndo )
 {
 	// Creates the array that will be returned. It contains one or more created links (see #220).
 	var aCreatedLinks = new Array() ;
+	var isControl = FCKSelection.GetType() == 'Control' ;
+	var selectedElement = isControl && FCKSelection.GetSelectedElement() ;
 
 	// Remove any existing link in the selection.
-	FCK.ExecuteNamedCommand( 'Unlink', null, false, !!noUndo ) ;
+	// IE BUG: Unlinking a floating control selection that is not inside a link
+	// will collapse the selection. (#3677)
+	if ( !( isControl && !FCKTools.GetElementAscensor( selectedElement, 'a' ) ) )
+		FCK.ExecuteNamedCommand( 'Unlink', null, false, !!noUndo ) ;
 
 	if ( url.length > 0 )
 	{
 		// If there are several images, and you try to link each one, all the images get inside the link:
 		// <img><img> -> <a><img></a><img> -> <a><img><img></a> due to the call to 'CreateLink' (bug in IE)
-		if (FCKSelection.GetType() == 'Control')
+		if ( isControl )
 		{
 			// Create a link
 			var oLink = this.EditorDocument.createElement( 'A' ) ;
 			oLink.href = url ;
 
 			// Get the selected object
-			var oControl = FCKSelection.GetSelectedElement() ;
+			var oControl = selectedElement ;
 			// Put the link just before the object
 			oControl.parentNode.insertBefore(oLink, oControl) ;
 			// Move the object inside the link

+ 1 - 1
main/inc/lib/fckeditor/editor/_source/internals/fckdialog.js

@@ -79,7 +79,7 @@ var FCKDialog = ( function()
 		/**
 		 * Opens a dialog window using the standard dialog template.
 		 */
-		OpenDialog : function( dialogName, dialogTitle, dialogPage, width, height, customValue, parentWindow, resizable )
+		OpenDialog : function( dialogName, dialogTitle, dialogPage, width, height, customValue, resizable )
 		{
 			if ( !topDialog )
 				this.DisplayMainCover() ;

+ 38 - 10
main/inc/lib/fckeditor/editor/_source/internals/fckdomtools.js

@@ -488,18 +488,46 @@ var FCKDomTools =
 
 		for ( var i = 0 ; i < attributes.length ; i++ )
 		{
-			if ( FCKBrowserInfo.IsIE && attributes[i].nodeName == 'class' )
+			if ( FCKBrowserInfo.IsIE ) 
 			{
-				// IE has a strange bug. If calling removeAttribute('className'),
-				// the attributes collection will still contain the "class"
-				// attribute, which will be marked as "specified", even if the
-				// outerHTML of the element is not displaying the class attribute.
-				// Note : I was not able to reproduce it outside the editor,
-				// but I've faced it while working on the TC of #1391.
-				if ( element.className.length > 0 )
-					return true ;
+				var attributeNodeName = attributes[i].nodeName ;
+
+				if ( attributeNodeName.StartsWith( '_fck' ) ) 
+				{
+					/**
+					 * There are places in the FCKeditor code where HTML element objects
+					 * get values stored as properties (e.g. _fckxhtmljob).  In Internet 
+					 * Explorer, these are interpreted as attempts to set attributes on
+					 * the element.  
+					 *
+					 * http://msdn.microsoft.com/en-us/library/ms533026(VS.85).aspx#Accessing_Element_Pr
+					 *
+					 * Counting these as HTML attributes cripples 
+					 * FCK.Style.RemoveFromRange() once FCK.GetData() has been called.
+					 *
+					 * The above conditional prevents these internal properties being 
+					 * counted as attributes.
+					 *
+					 * refs #2156 and #2834
+					 */
+
+					continue ;
+				}
+
+				if ( attributeNodeName == 'class' ) 
+				{
+					// IE has a strange bug. If calling removeAttribute('className'),
+					// the attributes collection will still contain the "class"
+					// attribute, which will be marked as "specified", even if the
+					// outerHTML of the element is not displaying the class attribute.
+					// Note : I was not able to reproduce it outside the editor,
+					// but I've faced it while working on the TC of #1391.
+					if ( element.className.length > 0 )
+						return true ;
+					continue ;
+				}
 			}
-			else if ( attributes[i].specified )
+			if ( attributes[i].specified )
 				return true ;
 		}
 

+ 17 - 0
main/inc/lib/fckeditor/editor/_source/internals/fckxhtml.js

@@ -56,6 +56,23 @@ FCKXHtml.GetXHTML = function( node, includeNode, format )
 	else
 		this._AppendChildNodes( this.MainNode, node, false ) ;
 
+	/**
+	 * FCKXHtml._AppendNode() marks DOM element objects it has 
+	 * processed by adding a property called _fckxhtmljob, 
+	 * setting it equal to the value of FCKXHtml.CurrentJobNum.  
+	 * On Internet Explorer, if an element object has such a 
+	 * property,  it will show up in the object's attributes 
+	 * NamedNodeMap, and the corresponding Attr object in 
+	 * that collection  will have is specified property set 
+	 * to true.  This trips up code elsewhere that checks to 
+	 * see if an element is free of attributes before proceeding 
+	 * with an edit operation (c.f. FCK.Style.RemoveFromRange())
+	 *	
+	 * refs #2156 and #2834
+	 */
+	if ( FCKBrowserInfo.IsIE )
+		FCKXHtml._RemoveXHtmlJobProperties( node ) ;
+
 	// Get the resulting XHTML as a string.
 	var sXHTML = this._GetMainXmlString() ;
 

+ 36 - 0
main/inc/lib/fckeditor/editor/_source/internals/fckxhtml_ie.js

@@ -92,6 +92,42 @@ FCKXHtml._AppendAttributes = function( xmlNode, htmlNode, node, nodeName )
 	}
 }
 
+/**
+ * Used to clean up HTML that has been processed FCKXHtml._AppendNode().
+ *
+ * For objects corresponding to HTML elements, Internet Explorer will 
+ * treat a property as if it were an attribute set on that element.
+ *
+ * http://msdn.microsoft.com/en-us/library/ms533026(VS.85).aspx#Accessing_Element_Pr
+ *
+ * FCKXHtml._AppendNode() sets the property _fckxhtmljob on node objects
+ * corresponding HTML elements to mark them as having been processed.
+ * Counting these properties as attributes will cripple style removal
+ * because FCK.Styles.RemoveFromSelection() will not remove an element
+ * as long as it still has attributes.
+ *
+ * refs #2156 and #2834
+ */
+
+FCKXHtml._RemoveXHtmlJobProperties = function ( node ) 
+{
+	// Select only nodes of type ELEMENT_NODE
+	if (!node || !node.nodeType || node.nodeType != 1)
+		return ;
+
+	// Clear the _fckhtmljob attribute.
+	if ( typeof node._fckxhtmljob !== 'undefined' )
+		node.removeAttribute('_fckxhtmljob') ;
+
+	// Recurse upon child nodes.
+	if ( node.hasChildNodes() ) 
+	{
+		var childNodes = node.childNodes ;
+		for ( var i = childNodes.length - 1 ; i >= 0 ; i-- ) 
+			FCKXHtml._RemoveXHtmlJobProperties( childNodes.item(i) ) ;
+	}
+}
+
 // On very rare cases, IE is loosing the "align" attribute for DIV. (right align and apply bulleted list)
 FCKXHtml.TagProcessors['div'] = function( node, htmlNode )
 {

+ 1 - 1
main/inc/lib/fckeditor/editor/dialog/common/fck_dialog_common.js

@@ -216,7 +216,7 @@ function OpenFileBrowser( url, width, height )
 	}
 	else
 	{
-		FCKDialog.OpenDialog( 'FCKDialog_FileManager' , FCKLang['BrowseServer'], url, width, height, '', window, true ) ;
+		FCKDialog.OpenDialog( 'FCKDialog_FileManager' , FCKLang['BrowseServer'], url, width, height, '', true ) ;
 	}
 }
 

+ 6 - 1
main/inc/lib/fckeditor/editor/dialog/fck_about.html

@@ -65,6 +65,11 @@ window.onload = function()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<div id="divAbout">
@@ -79,7 +84,7 @@ window.onload = function()
 								<span fcklang="DlgAboutVersion">version</span>
 								<br />
 								<b>2.6.4.1</b><br />
-								Build 23195</td>
+								Build 23405</td>
 						</tr>
 					</table>
 				</td>

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_anchor.html

@@ -200,6 +200,11 @@ function ReadjustLinksToAnchor( sCurrent, sNew )
 }
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body style="overflow: hidden">
 		<table height="100%" width="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_button.html

@@ -68,6 +68,11 @@ function Ok()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table width="100%" style="height: 100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_checkbox.html

@@ -75,6 +75,11 @@ function Ok()
 }
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body style="OVERFLOW: hidden" scroll="no">
 		<table height="100%" width="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_colorselector.html

@@ -142,6 +142,11 @@ function Ok()
 	return true ;
 }
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body onload="OnLoad()" scroll="no" style="OVERFLOW: hidden">
 		<table cellpadding="0" cellspacing="0" border="0" width="100%" height="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_div.html

@@ -319,6 +319,11 @@ function Ok()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<div id="divGeneral">

+ 22 - 17
main/inc/lib/fckeditor/editor/dialog/fck_docprops.html

@@ -21,11 +21,11 @@
  *
  * Link dialog window.
 -->
-<html xmlns="http://www.w3.org/1999/xhtml">
+<html>
 <head>
 	<title></title>
-	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
-	<meta content="noindex, nofollow" name="robots" />
+	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" >
+	<meta content="noindex, nofollow" name="robots" >
 	<script src="common/fck_dialog_common.js" type="text/javascript"></script>
 	<script type="text/javascript">
 
@@ -374,11 +374,11 @@ function SelectColor( wich )
 {
 	switch ( wich )
 	{
-		case 'Back'			: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectBackColor, window ) ; return ;
-		case 'ColorText'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorText, window ) ; return ;
-		case 'ColorLink'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorLink, window ) ; return ;
-		case 'ColorVisited'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorVisited, window ) ; return ;
-		case 'ColorActive'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorActive, window ) ; return ;
+		case 'Back'			: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectBackColor ) ; return ;
+		case 'ColorText'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorText ) ; return ;
+		case 'ColorLink'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorLink ) ; return ;
+		case 'ColorVisited'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorVisited ) ; return ;
+		case 'ColorActive'	: oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, SelectColorActive ) ; return ;
 	}
 }
 
@@ -394,6 +394,11 @@ function SetUrl( url )
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table cellspacing="0" cellpadding="0" width="100%" border="0" style="height: 100%">
@@ -458,22 +463,22 @@ function SetUrl( url )
 								<span fcklang="DlgDocDocType">Document Type Heading</span><br />
 								<select id="selDocType" onchange="CheckOther( this, 'txtDocType' );">
 									<option value="" selected="selected"></option>
-									<option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">'>HTML
+									<option value='&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"&gt;'>HTML
 										4.01 Transitional</option>
-									<option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">'>
+									<option value='&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;'>
 										HTML 4.01 Strict</option>
-									<option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'>
+									<option value='&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd"&gt;'>
 										HTML 4.01 Frameset</option>
-									<option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'>
+									<option value='&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;'>
 										XHTML 1.0 Transitional</option>
-									<option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'>
+									<option value='&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;'>
 										XHTML 1.0 Strict</option>
-									<option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">'>
+									<option value='&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd"&gt;'>
 										XHTML 1.0 Frameset</option>
-									<option value='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'>
+									<option value='&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"&gt;'>
 										XHTML 1.1</option>
-									<option value='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">'>HTML 3.2</option>
-									<option value='<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">'>HTML 2.0</option>
+									<option value='&lt;!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"&gt;'>HTML 3.2</option>
+									<option value='&lt;!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"&gt;'>HTML 2.0</option>
 									<option value="..." fcklang="DlgOpOther">&lt;Other&gt;</option>
 								</select>
 							</td>

+ 1 - 1
main/inc/lib/fckeditor/editor/dialog/fck_docprops/fck_document_preview.html

@@ -26,7 +26,7 @@
 		<title>Document Properties - Preview</title>
 		<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 		<meta name="robots" content="noindex, nofollow">
-		<script language="javascript">
+		<script type="text/javascript">
 
 var eBase = parent.FCK.EditorDocument.getElementsByTagName( 'BASE' ) ;
 if ( eBase.length > 0 && eBase[0].href.length > 0 )

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_flash.html

@@ -33,6 +33,11 @@
 document.write( FCKTools.GetStyleHtml( GetCommonDialogCss() ) ) ;
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body scroll="no" style="OVERFLOW: hidden">
 		<div id="divInfo">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_form.html

@@ -74,6 +74,11 @@ function Ok()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table width="100%" style="height: 100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_hiddenfield.html

@@ -89,6 +89,11 @@ function Ok()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden" scroll="no">
 	<table height="100%" width="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_image.html

@@ -33,6 +33,11 @@
 document.write( FCKTools.GetStyleHtml( GetCommonDialogCss() ) ) ;
 
 		</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body scroll="no" style="overflow: hidden">
 	<div id="divInfo">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_link.html

@@ -28,6 +28,11 @@
 		<meta name="robots" content="noindex, nofollow" />
 		<script src="common/fck_dialog_common.js" type="text/javascript"></script>
 		<script src="fck_link/fck_link.js" type="text/javascript"></script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body scroll="no" style="OVERFLOW: hidden">
 		<div id="divInfo" style="DISPLAY: none">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_listprop.html

@@ -82,6 +82,11 @@ function Ok()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table width="100%" style="height: 100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_paste.html

@@ -305,6 +305,11 @@ function CleanWord( oNode, bIgnoreFont, bRemoveStyles )
 
 	</script>
 
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table cellspacing="0" cellpadding="0" width="100%" border="0" style="height: 98%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_radiobutton.html

@@ -75,6 +75,11 @@ function Ok()
 }
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body style="OVERFLOW: hidden" scroll="no">
 		<table height="100%" width="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_replace.html

@@ -577,6 +577,11 @@ window.onunload = function()
 	}
 }
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body onload="OnLoad()" style="overflow: hidden">
 	<div id="divFind" style="display: none">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_select.html

@@ -115,6 +115,11 @@ function Ok()
 }
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body style="overflow: hidden">
 		<table width="100%" height="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_smiley.html

@@ -77,6 +77,11 @@ function out(td)
 	td.className = 'DarkBackground Hand' ;
 }
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table cellpadding="2" cellspacing="2" align="center" border="0" width="100%" height="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_source.html

@@ -57,6 +57,11 @@ function Ok()
 	return true ;
 }
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body scroll="no" style="OVERFLOW: hidden">
 		<table width="100%" height="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_specialchar.html

@@ -75,6 +75,11 @@ function setDefaults()
 }
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 13px; }
+		</style>
+
 	</head>
 	<body onload="setDefaults()" style="overflow: hidden">
 		<table cellpadding="0" cellspacing="0" width="100%" height="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_spellerpages.html

@@ -62,6 +62,11 @@ function oSpeller_OnFinished( numberOCorrections )
 }
 
 		</script>
+
+		<style type="text/css">
+			body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+		</style>
+
 	</head>
 	<body style="OVERFLOW: hidden" scroll="no" style="padding:0px;">
 		<input type="hidden" id="txtHtml" value="">

+ 0 - 148
main/inc/lib/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.cfm

@@ -1,148 +0,0 @@
-<cfsetting enablecfoutputonly="true">
-<!---
-This code uses a CF User Defined Function and should work in CF version 5.0
-and up without alteration.
-
-Also if you are hosting your site at an ISP, you will have to check with them
-to see if the use of <CFEXECUTE> is allowed. In most cases ISP will not allow
-the use of that tag for security reasons. Clients would be able to access each
-others files in certain cases.
---->
-
-<!--- The following variables values must reflect your installation. --->
-<cfset aspell_dir	  = "C:\Program Files\Aspell\bin">
-<cfset lang         = "en_US">
-<cfset aspell_opts  = "-a --lang=#lang# --encoding=utf-8 -H --rem-sgml-check=alt">
-<cfset tempfile_in  = GetTempFile(GetTempDirectory(), "spell_")>
-<cfset tempfile_out = GetTempFile(GetTempDirectory(), "spell_")>
-<cfset spellercss   = "../spellerStyle.css">
-<cfset word_win_src = "../wordWindow.js">
-
-<cfset form.checktext = form["textinputs[]"]>
-
-<!--- make no difference between URL and FORM scopes --->
-<cfparam name="url.checktext"  default="">
-<cfparam name="form.checktext" default="#url.checktext#">
-
-<!--- Takes care of those pesky smart quotes from MS apps, replaces them with regular quotes --->
-<cfset submitted_text = ReplaceList(form.checktext,"%u201C,%u201D","%22,%22")>
-
-<!--- submitted_text now is ready for processing --->
-
-<!--- use carat on each line to escape possible aspell commands --->
-<cfset text = "">
-<cfset CRLF = Chr(13) & Chr(10)>
-
-<cfloop list="#submitted_text#" index="field" delimiters=",">
-	<cfset text = text & "%"  & CRLF
-                      & "^A" & CRLF
-                      & "!"  & CRLF>
-	<!--- Strip all tags for the text. (by FredCK - #339 / #681) --->
-	<cfset field = REReplace(URLDecode(field), "<[^>]+>", " ", "all")>
-	<cfloop list="#field#" index="line" delimiters="#CRLF#">
-		<cfset text = ListAppend(text, "^" & Trim(JSStringFormat(line)), CRLF)>
-	</cfloop>
-</cfloop>
-
-<!--- create temp file from the submitted text, this will be passed to aspell to be check for misspelled words --->
-<cffile action="write" file="#tempfile_in#" output="#text#" charset="utf-8">
-
-<!--- execute aspell in an UTF-8 console and redirect output to a file. UTF-8 encoding is lost if done differently --->
-<cfexecute name="cmd.exe" arguments='/c type "#tempfile_in#" | "#aspell_dir#\aspell.exe" #aspell_opts# > "#tempfile_out#"' timeout="100"/>
-
-<!--- read output file for further processing --->
-<cffile action="read" file="#tempfile_out#" variable="food" charset="utf-8">
-
-<!--- remove temp files --->
-<cffile action="delete" file="#tempfile_in#">
-<cffile action="delete" file="#tempfile_out#">
-
-<cfset texts = StructNew()>
-<cfset texts.textinputs = "">
-<cfset texts.words      = "">
-<cfset texts.abort      = "">
-
-<!--- Generate Text Inputs --->
-<cfset i = 0>
-<cfloop list="#submitted_text#" index="textinput">
-  <cfset texts.textinputs = ListAppend(texts.textinputs, 'textinputs[#i#] = decodeURIComponent("#textinput#");', CRLF)>
-  <cfset i = i + 1>
-</cfloop>
-
-<!--- Generate Words Lists --->
-<cfset word_cnt  = 0>
-<cfset input_cnt = -1>
-<cfloop list="#food#" index="aspell_line" delimiters="#CRLF#">
-    <cfset leftChar = Left(aspell_line, 1)>
-	<cfif leftChar eq "*">
-			<cfset input_cnt   = input_cnt + 1>
-			<cfset word_cnt    = 0>
-			<cfset texts.words = ListAppend(texts.words, "words[#input_cnt#] = [];", CRLF)>
-			<cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#] = [];", CRLF)>
-    <cfelse>
-        <cfif leftChar eq "&" or leftChar eq "##">
-			<!--- word that misspelled --->
-			<cfset bad_word    = Trim(ListGetAt(aspell_line, 2, " "))>
-			<cfset bad_word    = Replace(bad_word, "'", "\'", "ALL")>
-			<!--- sugestions --->
-			<cfset sug_list    = Trim(ListRest(aspell_line, ":"))>
-			<cfset sug_list    = ListQualify(Replace(sug_list, "'", "\'", "ALL"), "'")>
-			<!--- javascript --->
-			<cfset texts.words = ListAppend(texts.words, "words[#input_cnt#][#word_cnt#] = '#bad_word#';", CRLF)>
-			<cfset texts.words = ListAppend(texts.words, "suggs[#input_cnt#][#word_cnt#] = [#sug_list#];", CRLF)>
-			<cfset word_cnt    = word_cnt + 1>
-		</cfif>
-     </cfif>
-</cfloop>
-
-<cfif texts.words eq "">
-  <cfset texts.abort = "alert('Spell check complete.\n\nNo misspellings found.'); top.window.close();">
-</cfif>
-
-<cfcontent type="text/html; charset=utf-8">
-
-<cfoutput><html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link rel="stylesheet" type="text/css" href="#spellercss#" />
-<script language="javascript" src="#word_win_src#"></script>
-<script language="javascript">
-var suggs      = new Array();
-var words      = new Array();
-var textinputs = new Array();
-var error;
-
-#texts.textinputs##CRLF#
-#texts.words#
-#texts.abort#
-
-var wordWindowObj = new wordWindow();
-wordWindowObj.originalSpellings = words;
-wordWindowObj.suggestions = suggs;
-wordWindowObj.textInputs = textinputs;
-
-function init_spell() {
-	// check if any error occured during server-side processing
-	if( error ) {
-		alert( error );
-	} else {
-		// call the init_spell() function in the parent frameset
-		if (parent.frames.length) {
-			parent.init_spell( wordWindowObj );
-		} else {
-			alert('This page was loaded outside of a frameset. It might not display properly');
-		}
-	}
-}
-</script>
-
-</head>
-<body onLoad="init_spell();">
-
-<script type="text/javascript">
-wordWindowObj.writeBody();
-</script>
-
-</body>
-</html></cfoutput>
-<cfsetting enablecfoutputonly="false">

+ 0 - 181
main/inc/lib/fckeditor/editor/dialog/fck_spellerpages/spellerpages/server-scripts/spellchecker.pl

@@ -1,181 +0,0 @@
-#!/usr/bin/perl
-
-use CGI qw/ :standard /;
-use File::Temp qw/ tempfile tempdir /;
-
-# my $spellercss = '/speller/spellerStyle.css';					# by FredCK
-my $spellercss = '../spellerStyle.css';							# by FredCK
-# my $wordWindowSrc = '/speller/wordWindow.js';					# by FredCK
-my $wordWindowSrc = '../wordWindow.js';							# by FredCK
-my @textinputs = param( 'textinputs[]' ); # array
-# my $aspell_cmd = 'aspell';									# by FredCK (for Linux)
-my $aspell_cmd = '"C:\Program Files\Aspell\bin\aspell.exe"';	# by FredCK (for Windows)
-my $lang = 'en_US';
-# my $aspell_opts = "-a --lang=$lang --encoding=utf-8";			# by FredCK
-my $aspell_opts = "-a --lang=$lang --encoding=utf-8 -H --rem-sgml-check=alt";		# by FredCK
-my $input_separator = "A";
-
-# set the 'wordtext' JavaScript variable to the submitted text.
-sub printTextVar {
-	for( my $i = 0; $i <= $#textinputs; $i++ ) {
-	        print "textinputs[$i] = decodeURIComponent('" . escapeQuote( $textinputs[$i] ) . "')\n";
-	}
-}
-
-sub printTextIdxDecl {
-	my $idx = shift;
-	print "words[$idx] = [];\n";
-	print "suggs[$idx] = [];\n";
-}
-
-sub printWordsElem {
-	my( $textIdx, $wordIdx, $word ) = @_;
-	print "words[$textIdx][$wordIdx] = '" . escapeQuote( $word ) . "';\n";
-}
-
-sub printSuggsElem {
-	my( $textIdx, $wordIdx, @suggs ) = @_;
-	print "suggs[$textIdx][$wordIdx] = [";
-	for my $i ( 0..$#suggs ) {
-		print "'" . escapeQuote( $suggs[$i] ) . "'";
-		if( $i < $#suggs ) {
-			print ", ";
-		}
-	}
-	print "];\n";
-}
-
-sub printCheckerResults {
-	my $textInputIdx = -1;
-	my $wordIdx = 0;
-	my $unhandledText;
-	# create temp file
-	my $dir = tempdir( CLEANUP => 1 );
-	my( $fh, $tmpfilename ) = tempfile( DIR => $dir );
-
-	# temp file was created properly?
-
-	# open temp file, add the submitted text.
-	for( my $i = 0; $i <= $#textinputs; $i++ ) {
-		$text = url_decode( $textinputs[$i] );
-		# Strip all tags for the text. (by FredCK - #339 / #681)
-		$text =~ s/<[^>]+>/ /g;
-		@lines = split( /\n/, $text );
-		print $fh "\%\n"; # exit terse mode
-		print $fh "^$input_separator\n";
-		print $fh "!\n";  # enter terse mode
-		for my $line ( @lines ) {
-			# use carat on each line to escape possible aspell commands
-			print $fh "^$line\n";
-		}
-
-	}
-	# exec aspell command
-	my $cmd = "$aspell_cmd $aspell_opts < $tmpfilename 2>&1";
-	open ASPELL, "$cmd |" or handleError( "Could not execute `$cmd`\\n$!" ) and return;
-	# parse each line of aspell return
-	for my $ret ( <ASPELL> ) {
-		chomp( $ret );
-		# if '&', then not in dictionary but has suggestions
-		# if '#', then not in dictionary and no suggestions
-		# if '*', then it is a delimiter between text inputs
-		if( $ret =~ /^\*/ ) {
-			$textInputIdx++;
-			printTextIdxDecl( $textInputIdx );
-			$wordIdx = 0;
-
-		} elsif( $ret =~ /^(&|#)/ ) {
-			my @tokens = split( " ", $ret, 5 );
-			printWordsElem( $textInputIdx, $wordIdx, $tokens[1] );
-			my @suggs = ();
-			if( $tokens[4] ) {
-				@suggs = split( ", ", $tokens[4] );
-			}
-			printSuggsElem( $textInputIdx, $wordIdx, @suggs );
-			$wordIdx++;
-		} else {
-			$unhandledText .= $ret;
-		}
-	}
-	close ASPELL or handleError( "Error executing `$cmd`\\n$unhandledText" ) and return;
-}
-
-sub escapeQuote {
-	my $str = shift;
-	$str =~ s/'/\\'/g;
-	return $str;
-}
-
-sub handleError {
-	my $err = shift;
-	print "error = '" . escapeQuote( $err ) . "';\n";
-}
-
-sub url_decode {
-	local $_ = @_ ? shift : $_;
-	defined or return;
-	# change + signs to spaces
-	tr/+/ /;
-	# change hex escapes to the proper characters
-	s/%([a-fA-F0-9]{2})/pack "H2", $1/eg;
-	return $_;
-}
-
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-# Display HTML
-# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
-
-print <<EOF;
-Content-type: text/html; charset=utf-8
-
-<html>
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
-<link rel="stylesheet" type="text/css" href="$spellercss"/>
-<script src="$wordWindowSrc"></script>
-<script type="text/javascript">
-var suggs = new Array();
-var words = new Array();
-var textinputs = new Array();
-var error;
-EOF
-
-printTextVar();
-
-printCheckerResults();
-
-print <<EOF;
-var wordWindowObj = new wordWindow();
-wordWindowObj.originalSpellings = words;
-wordWindowObj.suggestions = suggs;
-wordWindowObj.textInputs = textinputs;
-
-
-function init_spell() {
-	// check if any error occured during server-side processing
-	if( error ) {
-		alert( error );
-	} else {
-		// call the init_spell() function in the parent frameset
-		if (parent.frames.length) {
-			parent.init_spell( wordWindowObj );
-		} else {
-			error = "This page was loaded outside of a frameset. ";
-			error += "It might not display properly";
-			alert( error );
-		}
-	}
-}
-
-</script>
-
-</head>
-<body onLoad="init_spell();">
-
-<script type="text/javascript">
-wordWindowObj.writeBody();
-</script>
-
-</body>
-</html>
-EOF

+ 27 - 22
main/inc/lib/fckeditor/editor/dialog/fck_table.html

@@ -155,28 +155,6 @@ function Ok()
 	SetAttribute( table, 'cellSpacing'	, GetE('txtCellSpacing').value ) ;
 	SetAttribute( table, 'summary'		, GetE('txtSummary').value ) ;
 
-	var eCaption = oEditor.FCKDomTools.GetFirstChild( table, 'CAPTION' ) ;
-
-	if ( document.getElementById('txtCaption').value != '')
-	{
-		if ( !eCaption )
-		{
-			eCaption = oDoc.createElement( 'CAPTION' ) ;
-			table.insertBefore( eCaption, table.firstChild ) ;
-		}
-
-		eCaption.innerHTML = document.getElementById('txtCaption').value ;
-	}
-	else if ( bExists && eCaption )
-	{
-		// TODO: It causes an IE internal error if using removeChild or
-		// table.deleteCaption() (see #505).
-		if ( oEditor.FCKBrowserInfo.IsIE )
-			eCaption.innerHTML = '' ;
-		else
-			eCaption.parentNode.removeChild( eCaption ) ;
-	}
-
 	var headers = GetE('selHeaders').value ;
 	if ( bExists )
 	{
@@ -307,10 +285,37 @@ function Ok()
 		oEditor.FCK.InsertElement( table ) ;
 	}
 
+	var eCaption = oEditor.FCKDomTools.GetFirstChild( table, 'CAPTION' ) ;
+
+	if ( document.getElementById('txtCaption').value != '' )
+	{
+		if ( !eCaption )
+		{
+			eCaption = oDoc.createElement( 'CAPTION' ) ;
+			table.insertBefore( eCaption, table.firstChild ) ;
+		}
+
+		eCaption.innerHTML = document.getElementById('txtCaption').value ;
+	}
+	else if ( bExists && eCaption )
+	{
+		// TODO: It causes an IE internal error if using removeChild or
+		// table.deleteCaption() (see #505).
+		if ( oEditor.FCKBrowserInfo.IsIE )
+			eCaption.innerHTML = '' ;
+		else
+			eCaption.parentNode.removeChild( eCaption ) ;
+	}
+
 	return true ;
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table id="otable" cellspacing="0" cellpadding="0" width="100%" border="0" style="height: 100%">

+ 8 - 3
main/inc/lib/fckeditor/editor/dialog/fck_tablecell.html

@@ -139,10 +139,15 @@ function SelectBorderColor( color )
 
 function SelectColor( wich )
 {
-	oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', oEditor.FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, wich == 'Back' ? SelectBackColor : SelectBorderColor, window ) ;
+	oEditor.FCKDialog.OpenDialog( 'FCKDialog_Color', oEditor.FCKLang.DlgColorTitle, 'dialog/fck_colorselector.html', 410, 320, wich == 'Back' ? SelectBackColor : SelectBorderColor ) ;
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body scroll="no" style="overflow: hidden">
 	<table cellspacing="0" cellpadding="0" width="100%" border="0" height="100%">
@@ -224,8 +229,8 @@ function SelectColor( wich )
 									 <span fcklang="DlgCellType">Cell Type</span>:</td>
 									<td colspan="2">
 										&nbsp; <select id="selCellType">
-											<option fcklang="DlgCellTypeData" value="td" />Data
-											<option fcklang="DlgCellTypeHeader" value="th" />Header
+											<option fcklang="DlgCellTypeData" value="td">Data</option>
+											<option fcklang="DlgCellTypeHeader" value="th">Header</option>
 										</select>
 								</tr>
 								<tr>

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_template.html

@@ -208,6 +208,11 @@ function SelectTemplate( index )
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body scroll="no" style="overflow: hidden; background-color: #ffffff;">
 	<table width="100%" style="height: 100%;" valign="top">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_textarea.html

@@ -69,6 +69,11 @@ function Ok()
 }
 
 		</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 	</head>
 	<body style="overflow: hidden">
 		<table height="100%" width="100%">

+ 5 - 0
main/inc/lib/fckeditor/editor/dialog/fck_textfield.html

@@ -85,6 +85,11 @@ function Ok()
 }
 
 	</script>
+
+	<style type="text/css">
+		body, td, input, textarea, select, label { font-family: Arial, Verdana, Geneva, helvetica, sans-serif; font-size: 11px; }
+	</style>
+
 </head>
 <body style="overflow: hidden">
 	<table width="100%" style="height: 100%">

Some files were not shown because too many files changed in this diff